GCC Code Coverage Report


Directory: ./
File: src/msrproto/DataConverter.cpp
Date: 2024-11-05 15:23:15
Exec Total Coverage
Lines: 44 68 64.7%
Branches: 27 98 27.6%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2021 Richard Hacker (lerichi at gmx dot net),
4 * Florian Pose (fp at igh dot de),
5 * Bjarne von Horn (vh at igh dot de).
6 *
7 * This file is part of the PdCom library.
8 *
9 * The PdCom library is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or (at your
12 * option) any later version.
13 *
14 * The PdCom library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the PdCom library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *****************************************************************************/
23
24 #include "DataConverter.h"
25
26 #include "ProtocolHandler.h"
27 #include "Variable.h"
28
29 #include <cmath>
30 #include <cstdint>
31 #include <cstring>
32 #include <pdcom5/Exception.h>
33 #include <pdcom5/Process.h>
34 #include <pdcom5/SizeTypeInfo.h>
35 #include <pdcom5/details.h>
36 #include <sstream>
37
38 using PdCom::impl::MsrProto::DataDecoder;
39 using PdCom::impl::MsrProto::DataEncoder;
40 using PdCom::impl::MsrProto::Variable;
41
42 24 void DataDecoder::readFromHexDec(
43 const char *s,
44 const Variable &var,
45 unsigned int blocksize)
46 {
47 24 resize(0);
48 24 resize(blocksize * var.totalSizeInBytes());
49 24 uint8_t *dst = reinterpret_cast<uint8_t *>(data());
50 size_t c1, c2;
51 24 const char *c = s;
52 static const uint8_t hexDecTable[] = {0, 1, 2, 3, 4, 5, 6, 7,
53 8, 9, 0, 0, 0, 0, 0, 0,
54 0, 10, 11, 12, 13, 14, 15};
55
56
4/8
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 24 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 24 times.
24 if (!s or strlen(s) < var.totalSizeInBytes() * 2)
57 throw ProtocolError("invalid hexvalue attribute");
58
59 24 size_t bytes = var.totalSizeInBytes();
60 115 do {
61 139 c1 = *c++ - '0';
62 139 c2 = *c++ - '0';
63
2/4
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 139 times.
139 if (c1 >= sizeof(hexDecTable) or c2 >= sizeof(hexDecTable))
64 throw ProtocolError("invalid hexvalue attribute");
65
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 139 times.
139 *dst++ = (hexDecTable[c1] << 4) + hexDecTable[c2];
66
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 24 times.
139 } while (--bytes);
67 24 }
68
69 //////////////////////////////////////////////////////////////////////
70 void DataDecoder::readFromString(
71 const char *s,
72 const Variable &var,
73 unsigned int blocksize)
74 {
75 if (!s)
76 throw ProtocolError("invalid value attribute");
77
78 const auto nelem = blocksize * var.numberOfElements();
79 resize(0);
80 resize(nelem * var.type_info->element_size);
81
82 std::istringstream is(s);
83 double src;
84
85
86 is.imbue(std::locale::classic());
87
88 for (size_t i = 0; i < nelem && is; ++i) {
89 if (i)
90 is.ignore(1);
91
92 // istream does not like nan
93 if (!strncmp("-nan", s + is.tellg(), 4)) {
94 is.ignore(4);
95 src = -NAN;
96 }
97 else {
98 is >> src;
99 }
100
101 PdCom::details::copyData(
102 data() + i * var.type_info->element_size, var.type_info->type,
103 &src, PdCom::TypeInfo::double_T, 1);
104 }
105
106 if (!is)
107 throw ProtocolError("invalid value attribute");
108 }
109
110
111 53 void DataDecoder::readFromBase64(
112 const char *s,
113 const size_t input_len,
114 const Variable &var,
115 unsigned int blocksize)
116 {
117 53 resize(0);
118 53 resize(blocksize * var.totalSizeInBytes()
119 + 2 /* buffer must be longer for padding */);
120 53 const size_t expected_size = blocksize * var.totalSizeInBytes();
121
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
53 if (!PdCom::impl::MsrProto::readFromBase64(
122 53 data(), s, input_len, expected_size))
123 throw ProtocolError("Invalid base64 value");
124 53 }
125
126 108 bool PdCom::impl::MsrProto::readFromBase64(
127 char *dst,
128 const char *base64,
129 const size_t len,
130 size_t buflen)
131 {
132 uint8_t c1, c2;
133 static const uint8_t base64Value[256] = {
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 62, 0, 63,
137 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
138 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
139 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63,
140 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
141 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0,
142 };
143
2/4
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 108 times.
108 if (!base64 or !*base64)
144 return false;
145
146
3/4
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 105 times.
108 if (len % 4 or len < 4)
147 3 return false;
148
149
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 103 times.
105 if (len / 4 != (buflen + 2) / 3)
150 2 return false;
151
152
2/2
✓ Branch 0 taken 251 times.
✓ Branch 1 taken 103 times.
354 for (const char *const end = base64 + len; base64 != end;) {
153 251 c1 = base64Value[uint8_t(*base64++)];
154 251 c2 = base64Value[uint8_t(*base64++)];
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251 times.
251 *dst++ = (c1 << 2) | (c2 >> 4);
156
157 251 c1 = base64Value[uint8_t(*base64++)];
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251 times.
251 *dst++ = (c2 << 4) | (c1 >> 2);
159
160 251 c2 = base64Value[uint8_t(*base64++)];
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 251 times.
251 *dst++ = (c1 << 6) | c2;
162 }
163
164 103 return true;
165 }
166
167 15 void DataEncoder::toHex(
168 PdCom::TypeInfo const &dst_type,
169 const void *src,
170 PdCom::TypeInfo::DataType src_type,
171 size_t n,
172 PdCom::impl::MsrProto::XmlStream &os)
173 {
174 15 converted_value_.resize(0);
175 15 converted_value_.resize(n * dst_type.element_size);
176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 details::copyData(converted_value_.data(), dst_type.type, src, src_type, n);
177
178 static constexpr char hexTable[] = {'0', '1', '2', '3', '4', '5', '6', '7',
179 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
180
181
2/2
✓ Branch 6 taken 35 times.
✓ Branch 7 taken 15 times.
50 for (const auto c : converted_value_)
182
2/4
✓ Branch 3 taken 35 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 35 times.
✗ Branch 8 not taken.
35 os << hexTable[c >> 4] << hexTable[c & 0x0F];
183
184 15 converted_value_.resize(0);
185 15 }
186