GCC Code Coverage Report


Directory: ./
File: pdcom5/src/msrproto/DataConverter.cpp
Date: 2024-11-17 04:08:36
Exec Total Coverage
Lines: 42 68 61.8%
Branches: 25 98 25.5%

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 49 void DataDecoder::readFromHexDec(
43 const char *s,
44 const Variable &var,
45 unsigned int blocksize)
46 {
47 49 resize(0);
48 49 resize(blocksize * var.totalSizeInBytes());
49 49 uint8_t *dst = reinterpret_cast<uint8_t *>(data());
50 size_t c1, c2;
51 49 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 49 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 49 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 49 times.
49 if (!s or strlen(s) < var.totalSizeInBytes() * 2)
57 throw ProtocolError("invalid hexvalue attribute");
58
59 49 size_t bytes = var.totalSizeInBytes();
60 671 do {
61 720 c1 = *c++ - '0';
62 720 c2 = *c++ - '0';
63
2/4
✓ Branch 0 taken 720 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 720 times.
720 if (c1 >= sizeof(hexDecTable) or c2 >= sizeof(hexDecTable))
64 throw ProtocolError("invalid hexvalue attribute");
65
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 720 times.
720 *dst++ = (hexDecTable[c1] << 4) + hexDecTable[c2];
66
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 49 times.
720 } while (--bytes);
67 49 }
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 548 void DataDecoder::readFromBase64(
112 const char *s,
113 const size_t input_len,
114 const Variable &var,
115 unsigned int blocksize)
116 {
117 548 resize(0);
118 548 resize(blocksize * var.totalSizeInBytes()
119 + 2 /* buffer must be longer for padding */);
120 548 const size_t expected_size = blocksize * var.totalSizeInBytes();
121
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 548 times.
548 if (!PdCom::impl::MsrProto::readFromBase64(
122 548 data(), s, input_len, expected_size))
123 throw ProtocolError("Invalid base64 value");
124 548 }
125
126 889 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 889 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 889 times.
889 if (!base64 or !*base64)
144 return false;
145
146
2/4
✓ Branch 0 taken 889 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 889 times.
889 if (len % 4 or len < 4)
147 return false;
148
149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 889 times.
889 if (len / 4 != (buflen + 2) / 3)
150 return false;
151
152
2/2
✓ Branch 0 taken 5925 times.
✓ Branch 1 taken 889 times.
6814 for (const char *const end = base64 + len; base64 != end;) {
153 5925 c1 = base64Value[uint8_t(*base64++)];
154 5925 c2 = base64Value[uint8_t(*base64++)];
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5925 times.
5925 *dst++ = (c1 << 2) | (c2 >> 4);
156
157 5925 c1 = base64Value[uint8_t(*base64++)];
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5925 times.
5925 *dst++ = (c2 << 4) | (c1 >> 2);
159
160 5925 c2 = base64Value[uint8_t(*base64++)];
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5925 times.
5925 *dst++ = (c1 << 6) | c2;
162 }
163
164 889 return true;
165 }
166
167 43 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 43 converted_value_.resize(0);
175 43 converted_value_.resize(n * dst_type.element_size);
176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 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 412 times.
✓ Branch 7 taken 43 times.
455 for (const auto c : converted_value_)
182
2/4
✓ Branch 3 taken 412 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 412 times.
✗ Branch 8 not taken.
412 os << hexTable[c >> 4] << hexTable[c & 0x0F];
183
184 43 converted_value_.resize(0);
185 43 }
186