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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy