GCC Code Coverage Report


Directory: ./
File: pdcom5/src/msrproto/DataConverter.cpp
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 58 69 84.1%
Branches: 47 98 48.0%

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 50 void DataDecoder::readFromHexDec(
43 const char *s,
44 const Variable &var,
45 unsigned int blocksize)
46 {
47 50 resize(0);
48 50 resize(blocksize * var.totalSizeInBytes());
49 50 uint8_t *dst = reinterpret_cast<uint8_t *>(data());
50 size_t c1, c2;
51 50 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 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 50 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 50 times.
50 if (!s or strlen(s) < var.totalSizeInBytes() * 2)
57 throw ProtocolError("invalid hexvalue attribute");
58
59 50 size_t bytes = var.totalSizeInBytes();
60 674 do {
61 724 c1 = *c++ - '0';
62 724 c2 = *c++ - '0';
63
2/4
✓ Branch 0 taken 724 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 724 times.
724 if (c1 >= sizeof(hexDecTable) or c2 >= sizeof(hexDecTable))
64 throw ProtocolError("invalid hexvalue attribute");
65
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 724 times.
724 *dst++ = (hexDecTable[c1] << 4) + hexDecTable[c2];
66
2/2
✓ Branch 0 taken 674 times.
✓ Branch 1 taken 50 times.
724 } while (--bytes);
67 50 }
68
69 //////////////////////////////////////////////////////////////////////
70 1 void DataDecoder::readFromString(
71 const char *s,
72 const Variable &var,
73 unsigned int blocksize)
74 {
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!s)
76 throw ProtocolError("invalid value attribute");
77
78 1 const auto nelem = blocksize * var.numberOfElements();
79
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 resize(0);
80
1/2
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 resize(nelem * var.type_info->element_size);
81
82
2/4
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
2 std::istringstream is(s);
83 1 double src;
84
85
86
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 is.imbue(std::locale::classic());
87
88
6/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
2 for (size_t i = 0; i < nelem && is; ++i) {
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (i)
90 is.ignore(1);
91
92 // istream does not like nan
93
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
1 if (!strncmp("-nan", s + is.tellg(), 4)) {
94 is.ignore(4);
95 src = -NAN;
96 }
97 else {
98
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 is >> src;
99 }
100
101
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 PdCom::details::copyData(
102
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 data() + i * var.type_info->element_size, var.type_info->type,
103 &src, PdCom::TypeInfo::double_T, 1);
104 }
105
106
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (!is)
107 throw ProtocolError("invalid value attribute");
108 1 }
109
110
111 95 void DataDecoder::readFromBase64(
112 const char *s,
113 const size_t input_len,
114 const Variable &var,
115 unsigned int blocksize)
116 {
117 95 resize(0);
118 95 resize(blocksize * var.totalSizeInBytes()
119 + 2 /* buffer must be longer for padding */);
120 95 const size_t expected_size = blocksize * var.totalSizeInBytes();
121
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 95 times.
95 if (!PdCom::impl::MsrProto::readFromBase64(
122 95 data(), s, input_len, expected_size))
123 throw ProtocolError("Invalid base64 value");
124 95 }
125
126 142 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 142 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 142 times.
142 if (!base64 or !*base64)
144 return false;
145
146
2/4
✓ Branch 0 taken 142 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 142 times.
142 if (len % 4 or len < 4)
147 return false;
148
149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 if (len / 4 != (buflen + 2) / 3)
150 return false;
151
152
2/2
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 142 times.
581 for (const char *const end = base64 + len; base64 != end;) {
153 439 c1 = base64Value[uint8_t(*base64++)];
154 439 c2 = base64Value[uint8_t(*base64++)];
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 *dst++ = (c1 << 2) | (c2 >> 4);
156
157 439 c1 = base64Value[uint8_t(*base64++)];
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 *dst++ = (c2 << 4) | (c1 >> 2);
159
160 439 c2 = base64Value[uint8_t(*base64++)];
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
439 *dst++ = (c1 << 6) | c2;
162 }
163
164 142 return true;
165 }
166
167 44 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 44 converted_value_.resize(0);
175 44 converted_value_.resize(n * dst_type.element_size);
176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
44 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 416 times.
✓ Branch 7 taken 44 times.
460 for (const auto c : converted_value_)
182
2/4
✓ Branch 3 taken 416 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 416 times.
✗ Branch 8 not taken.
416 os << hexTable[c >> 4] << hexTable[c & 0x0F];
183
184 44 converted_value_.resize(0);
185 44 }
186