Content-Length: 1031627 | pFad | https://github.com/astand/c-coderdbc/commit/b89d2ee4ee58221c7c62cdd1ae3b99bbcf5fd926

B8 Fixed floating parsing, better printing, removed duplication. · astand/c-coderdbc@b89d2ee · GitHub
Skip to content

Commit b89d2ee

Browse files
committed
Fixed floating parsing, better printing, removed duplication.
1 parent d63b36a commit b89d2ee

File tree

10 files changed

+284
-54
lines changed

10 files changed

+284
-54
lines changed

docs/RELEASES.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## v2.7
4+
5+
### Fixed
6+
7+
- Removed signal conversion macroses duplication ([issue #11](https://github.com/astand/c-coderdbc/issues/18))
8+
- More precise floating factor/offset values handling ([issue #10](https://github.com/astand/c-coderdbc/issues/20))
9+
10+
### Added
11+
12+
- Better print for floating factor/offset values (removed tailing zeros)
13+
- Signals with too low factor/offset values (less than 0.000000001) are considered as plain integer signals, it is up to client to handle them
14+
15+
---
16+
317
## v2.6 29.09.2022
418

519
### Fixed

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ add_executable(
4040
cctest
4141
${CMAKE_CURRENT_SOURCE_DIR}/helpers/formatter.cpp
4242
${CMAKE_CURRENT_SOURCE_DIR}/options-parser.cpp
43+
${CMAKE_CURRENT_SOURCE_DIR}/parser/dbclineparser.cpp
4344
${CMAKE_CURRENT_SOURCE_DIR}/tests/args-test.cpp
4445
${CMAKE_CURRENT_SOURCE_DIR}/tests/bitext-test.cpp
46+
${CMAKE_CURRENT_SOURCE_DIR}/tests/dbcline-test.cpp
4547
)
4648

4749
target_link_libraries(

src/codegen/c-main-generator.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <stdarg.h>
77
#include <filesystem>
88
#include <algorithm>
9+
#include <set>
910
#include <regex>
1011
#include "helpers/formatter.h"
1112
#include "mon-generator.h"
@@ -84,6 +85,8 @@ void CiMainGenerator::Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd
8485

8586
void CiMainGenerator::Gen_MainHeader()
8687
{
88+
std::set<std::string> passed_sigs;
89+
8790
// write comment start text
8891
if (fdesc->gen.start_info.size() > 0)
8992
{
@@ -148,7 +151,12 @@ void CiMainGenerator::Gen_MainHeader()
148151

149152
if (!s.IsSimpleSig)
150153
{
151-
fwriter->Append(sigprt->PrintPhysicalToRaw(&s, fdesc->gen.DRVNAME));
154+
if (passed_sigs.find(s.Name) == passed_sigs.end())
155+
{
156+
// print signal macroses only it was not printed before
157+
fwriter->Append(sigprt->PrintPhysicalToRaw(&s, fdesc->gen.DRVNAME));
158+
passed_sigs.insert(s.Name);
159+
}
152160
}
153161

154162
if (s.Name.size() > max_sig_name_len)
@@ -561,14 +569,14 @@ void CiMainGenerator::WriteSigStructField(const SignalDescriptor_t& sig, bool bi
561569
{
562570
infocmnt = IndentedString(offset, infocmnt);
563571
offset += 27;
564-
infocmnt += StrPrint(" Offset= %f", sig.Offset);
572+
infocmnt += StrPrint(" Offset= %s", prt_double(sig.Offset, 9));
565573
}
566574

567575
if (sig.Factor != 1)
568576
{
569577
infocmnt = IndentedString(offset, infocmnt);
570578
offset += 24;
571-
infocmnt += StrPrint(" Factor= %f", sig.Factor);
579+
infocmnt += StrPrint(" Factor= %s", prt_double(sig.Factor, 9));
572580
}
573581
}
574582
else if (sig.IsSimpleSig == false)

src/codegen/c-sigprinter.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,14 @@ std::string CSigPrinter::PrintPhysicalToRaw(const SignalDescriptor_t* sig, const
5454
{
5555
std::string retstr = "";
5656

57+
const std::string prtFactor = prt_double(sig->Factor, 9);
58+
const std::string prtOffset = prt_double(sig->Offset, 9);
59+
5760
retstr = StrPrint("// signal: @%s\n", sig->Name.c_str());
5861

5962
if (sig->IsDoubleSig)
6063
{
61-
retstr += StrPrint("#define %s_%s_CovFactor (%f)\n", drvname.c_str(), sig->Name.c_str(), sig->Factor);
64+
retstr += StrPrint("#define %s_%s_CovFactor (%s)\n", drvname.c_str(), sig->Name.c_str(), prtFactor.c_str());
6265
}
6366
else
6467
{
@@ -70,7 +73,7 @@ std::string CSigPrinter::PrintPhysicalToRaw(const SignalDescriptor_t* sig, const
7073

7174
if (sig->IsDoubleSig)
7275
{
73-
retstr += StrPrint("(((x) - (%f)) / (%f)) )\n", sig->Offset, sig->Factor);
76+
retstr += StrPrint("(((x) - (%s)) / (%s)) )\n", prtOffset.c_str(), prtFactor.c_str());
7477
}
7578
else
7679
{
@@ -95,7 +98,7 @@ std::string CSigPrinter::PrintPhysicalToRaw(const SignalDescriptor_t* sig, const
9598

9699
if (sig->IsDoubleSig)
97100
{
98-
retstr += StrPrint("(((x) * (%f)) + (%f)) )\n", sig->Factor, sig->Offset);
101+
retstr += StrPrint("(((x) * (%s)) + (%s)) )\n", prtFactor.c_str(), prtOffset.c_str());
99102
}
100103
else
101104
{

src/codegen/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
#include <stdint.h>
44

55
#define CODEGEN_LIB_VERSION_MAJ (2)
6-
#define CODEGEN_LIB_VERSION_MIN (5)
6+
#define CODEGEN_LIB_VERSION_MIN (7)

src/helpers/formatter.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,60 @@ std::string make_c_name(const std::string& s)
143143

144144
return ret;
145145
}
146+
147+
const char* prt_double(double value, size_t presicsion, bool usedot)
148+
{
149+
constexpr size_t MAX_CAP = 1024u;
150+
151+
static char buff[MAX_CAP] = {0};
152+
153+
// sprint value with max precision (currently 15 digits)
154+
snprintf(buff, MAX_CAP, "%.15f", value);
155+
156+
size_t last_non_zero_id = 0u;
157+
size_t dot_id = 0u;
158+
size_t left_to_check = presicsion;
159+
160+
for (size_t i = 0u; i < MAX_CAP - 1u; i++)
161+
{
162+
if ((buff[i] == '.') && (last_non_zero_id == 0u))
163+
{
164+
// dot is detected
165+
last_non_zero_id = i;
166+
167+
if (usedot)
168+
{
169+
// forcibly leave at least 1 position after dot
170+
last_non_zero_id = i + 1u;
171+
}
172+
173+
dot_id = i;
174+
}
175+
else if (last_non_zero_id != 0u)
176+
{
177+
if ((left_to_check == 0u) || (buff[i] < '0') || (buff[i] > '9'))
178+
{
179+
break;
180+
}
181+
182+
if ((buff[i] > '0') && (buff[i] < '9'))
183+
{
184+
last_non_zero_id = i;
185+
}
186+
187+
left_to_check--;
188+
}
189+
}
190+
191+
if (last_non_zero_id == dot_id)
192+
{
193+
buff[dot_id] = '\0';
194+
}
195+
else
196+
{
197+
buff[last_non_zero_id + 1u] = '\0';
198+
}
199+
200+
return buff;
201+
}
202+

src/helpers/formatter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ std::string str_tolower(std::string s);
1717

1818
std::string str_trim(std::string s);
1919

20+
/// @brief Function prints double value with dropping tailing zeros
21+
/// @param value value to format
22+
/// @param presicsion maximal precision length
23+
/// @param usedot true for forcibly print presicion 1 (one digit after dot)
24+
/// @return pointer to internal char array with value representation
25+
const char* prt_double(double value, size_t presicsion, bool usedot = true);
26+
2027
/**
2128
* @brief Makes input string valid C-identifier
2229
*

src/parser/dbclineparser.cpp

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include <math.h>
77
#include <limits.h>
88

9+
/// @brief Minimal possible value for Factor/Offset
10+
constexpr double MIN_FAC_OFF = 0.000000001;
11+
912
// Message line definitions
1013
static const std::string regMessage = "[^A-Za-z0-9_.-]";
1114
static const std::string MessageLineStart = "BO_ ";
@@ -232,36 +235,50 @@ bool DbcLineParser::ParseSignalLine(SignalDescriptor_t* sig, const std::string&
232235

233236
// for enabling double conversation the factor or offset
234237
// substring must have dot ('.') character
235-
if (valpart[3].find_first_of('.') != std::string::npos ||
236-
valpart[4].find_first_of('.') != std::string::npos)
238+
if (valpart[3].find_first_of('.') != std::string::npos
239+
|| valpart[4].find_first_of('.') != std::string::npos
240+
|| valpart[3].find_first_of('E') != std::string::npos
241+
|| valpart[3].find_first_of('e') != std::string::npos
242+
|| valpart[4].find_first_of('E') != std::string::npos
243+
|| valpart[4].find_first_of('e') != std::string::npos
244+
)
237245
{
238246
sig->IsDoubleSig = true;
239247
}
240248

241-
// factor = double;
242-
// offset = double;
243-
//The factorand offset define the linear conversion rule to convert the signals raw
244-
//value into the signal's physical value and vice versa:
245-
// physical_value = raw_value * factor + offset
246-
// raw_value = (physical_value - offset) / factor
249+
// factor = double;
250+
// offset = double;
251+
//
252+
// The factorand offset define the linear conversion rule to convert the signals raw
253+
// value into the signal's physical value and vice versa:
254+
// physical_value = raw_value * factor + offset
255+
// raw_value = (physical_value - offset) / factor
247256
std::setlocale(LC_ALL, "en_US.UTF-8");
248257

249258
sig->Factor = atof(valpart[3].c_str());
250259
sig->Offset = atof(valpart[4].c_str());
251260

261+
if (((std::fabs(sig->Factor) < MIN_FAC_OFF) && (sig->Factor != 0.0)) ||
262+
((std::fabs(sig->Offset) < MIN_FAC_OFF) && (sig->Offset != 0.0)))
263+
{
264+
// this values are not supported, treat this signal as a plain integer
265+
sig->Factor = 1.0;
266+
sig->Offset = 0.0;
267+
sig->IsDoubleSig = false;
268+
}
269+
252270
sig->RawOffset = sig->Offset / sig->Factor;
253271

254272
sig->MinValue = atof(valpart[5].c_str());
255273
sig->MaxValue = atof(valpart[6].c_str());
256274

257275

258-
//The signal_size specifies the size of the signal in bits
259-
// byte_order = '0' | '1'; (*0 = little endian, 1 = big endian*)
276+
// Bytes layout
277+
// 0: Big endian (Motorolla)
278+
// 1: Little endian (Intel)
260279
sig->Order = (valpart[2].find('1') == std::string::npos) ? BitLayout::kMotorolla : BitLayout::kIntel;
261280

262-
//The byte_format is 0 if the signal's byte order is Intel (little endian) or 1 if the byte
263-
//order is Motorola(big endian).
264-
// value_type = '+' | '-'; (*+= unsigned, -=signed*)
281+
// value_type = '+' | '-'; (*+= unsigned, -=signed*)
265282
sig->Signed = (valpart[2].find('-') == std::string::npos) ? 0 : 1;
266283

267284
GetSigType(sig);

src/tests/dbcline-test.cpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include <stdlib.h>
2+
#include "testapi.h"
3+
#include "parser/dbclineparser.h"
4+
#include "helpers/formatter.h"
5+
6+
7+
TEST(TestSigLineParsing, test1)
8+
{
9+
DbcLineParser parser;
10+
11+
const std::string t2 = " SG_ FLT4_TEST_1 : 39|4@0+ (2.01,1E-002) [-0.01|30.14] \"\" BCM";
12+
13+
expect_true(parser.IsSignalLine(t2));
14+
15+
SignalDescriptor_t dsc;
16+
17+
parser.ParseSignalLine(&dsc, t2);
18+
19+
expect_true(dsc.IsDoubleSig);
20+
expect_true(dsc.Offset == 0.01);
21+
22+
const std::string t3 = " SG_ FLT4_TEST_1 : 39|4@0+ (2, 1) [-0.01|30.14] \"\" BCM";
23+
24+
parser.ParseSignalLine(&dsc, t3);
25+
26+
expect_false(dsc.IsDoubleSig);
27+
expect_true(dsc.Offset == 1.0);
28+
29+
// last supported double values
30+
const std::string t2_ok_norm = " SG_ FLT4_TEST_1 : 39|4@0+ (2, 0.000000001) [-0.01|30.14] \"\" BCM";
31+
const std::string t2_ok_scie = " SG_ FLT4_TEST_1 : 39|4@0+ (2, 1e-9) [-0.01|30.14] \"\" BCM";
32+
// next values (and less than) are not currently supported
33+
const std::string t2_nok_norm = " SG_ FLT4_TEST_1 : 39|4@0+ (2, 0.00000000099) [-0.01|30.14] \"\" BCM";
34+
const std::string t2_nok_scie = " SG_ FLT4_TEST_1 : 39|4@0+ (2, 1e-10) [-0.01|30.14] \"\" BCM";
35+
const std::string t3_nok_scie = " SG_ FLT4_TEST_1 : 39|4@0+ (1e-10, 44) [-0.01|30.14] \"\" BCM";
36+
const std::string t3_nok_norm = " SG_ FLT4_TEST_1 : 39|4@0+ (0.00000000099, 2) [-0.01|30.14] \"\" BCM";
37+
38+
parser.ParseSignalLine(&dsc, t2_ok_norm);
39+
40+
expect_true(dsc.IsDoubleSig);
41+
expect_eq(dsc.Offset, 0.000000001);
42+
expect_eq(dsc.Factor, 2.0);
43+
44+
parser.ParseSignalLine(&dsc, t2_ok_scie);
45+
46+
expect_true(dsc.IsDoubleSig);
47+
expect_eq(dsc.Offset, 0.000000001);
48+
expect_eq(dsc.Factor, 2.0);
49+
50+
parser.ParseSignalLine(&dsc, t3_nok_norm);
51+
52+
expect_false(dsc.IsDoubleSig);
53+
expect_eq(dsc.Offset, 0.0);
54+
expect_eq(dsc.Factor, 1.0);
55+
56+
parser.ParseSignalLine(&dsc, t3_nok_scie);
57+
58+
expect_false(dsc.IsDoubleSig);
59+
expect_eq(dsc.Offset, 0.0);
60+
expect_eq(dsc.Factor, 1.0);
61+
62+
}
63+
64+
TEST(TestSigLineParsing, test_02)
65+
{
66+
const std::string t3_ok = " SG_ FLT4_TEST_1 : 39|4@0+ (0.99, 0) [-0.01|30.14] \"\" BCM";
67+
const std::string t4_ok = " SG_ FLT4_TEST_1 : 39|4@0+ (0, -0.11) [-0.01|30.14] \"\" BCM";
68+
const std::string t5_notok = " SG_ FLT4_TEST_1 : 39|4@0+ (0.00000000099, 0) [-0.01|30.14] \"\" BCM";
69+
const std::string t6_ok = " SG_ FLT4_TEST_1 : 39|4@0+ (0, 0.000000000000) [-0.01|30.14] \"\" BCM";
70+
71+
DbcLineParser parser;
72+
73+
SignalDescriptor_t dsc;
74+
75+
parser.ParseSignalLine(&dsc, t3_ok);
76+
77+
expect_true(dsc.IsDoubleSig);
78+
79+
parser.ParseSignalLine(&dsc, t4_ok);
80+
81+
expect_true(dsc.IsDoubleSig);
82+
expect_eq(dsc.Factor, 0.0);
83+
expect_eq(dsc.Offset, -0.11);
84+
85+
parser.ParseSignalLine(&dsc, t5_notok);
86+
87+
expect_false(dsc.IsDoubleSig);
88+
expect_eq(dsc.Factor, 1.0);
89+
expect_eq(dsc.Offset, 0.0);
90+
91+
parser.ParseSignalLine(&dsc, t6_ok);
92+
93+
expect_true(dsc.IsDoubleSig);
94+
expect_eq(dsc.Factor, 0.0);
95+
expect_eq(dsc.Offset, 0.0);
96+
97+
}
98+
99+
TEST(TestSigLineParsing, test_prt_double)
100+
{
101+
constexpr double v = -124.10001110002220;
102+
103+
expect_eq((std::string)prt_double(v, 0, false), (std::string)"-124");
104+
expect_eq((std::string)prt_double(v, 1, false), (std::string)"-124.1");
105+
expect_eq((std::string)prt_double(v, 2, false), (std::string)"-124.1");
106+
expect_eq((std::string)prt_double(v, 3, false), (std::string)"-124.1");
107+
expect_eq((std::string)prt_double(v, 4, false), (std::string)"-124.1");
108+
expect_eq((std::string)prt_double(v, 5, false), (std::string)"-124.10001");
109+
expect_eq((std::string)prt_double(v, 6, false), (std::string)"-124.100011");
110+
expect_eq((std::string)prt_double(v, 7, false), (std::string)"-124.1000111");
111+
expect_eq((std::string)prt_double(v, 8, false), (std::string)"-124.1000111");
112+
expect_eq((std::string)prt_double(v, 9, false), (std::string)"-124.1000111");
113+
114+
constexpr double vint = 123.0000;
115+
116+
expect_eq((std::string)prt_double(vint, 3), (std::string)"123.0");
117+
expect_eq((std::string)prt_double(vint, 2), (std::string)"123.0");
118+
expect_eq((std::string)prt_double(vint, 1), (std::string)"123.0");
119+
expect_eq((std::string)prt_double(vint, 0), (std::string)"123.0");
120+
expect_eq((std::string)prt_double(vint, 100), (std::string)"123.0");
121+
expect_eq((std::string)prt_double(vint, 1000), (std::string)"123.0");
122+
123+
constexpr double v2 = 0.0110022;
124+
125+
expect_eq((std::string)prt_double(v2, 0), "0.0");
126+
}

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: https://github.com/astand/c-coderdbc/commit/b89d2ee4ee58221c7c62cdd1ae3b99bbcf5fd926

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy