GCC Code Coverage Report


Directory: ./
File: include/pdcom5/DataDeserializer.h
Date: 2024-11-05 15:23:15
Exec Total Coverage
Lines: 43 46 93.5%
Branches: 104 266 39.1%

Line Branch Exec Source
1 /*****************************************************************************
2 * vim:tw=78
3 *
4 * Copyright (C) 2022 Richard Hacker (lerichi at gmx dot net),
5 * Florian Pose (fp at igh dot de),
6 * Bjarne von Horn (vh at igh dot de).
7 *
8 * This file is part of the PdCom library.
9 *
10 * The PdCom library is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or (at your
13 * option) any later version.
14 *
15 * The PdCom library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with the PdCom library. If not, see <http://www.gnu.org/licenses/>.
22 *
23 *****************************************************************************/
24
25 /** @file */
26
27 #ifndef PDCOM5_DATADESERIALIZER_H
28 #define PDCOM5_DATADESERIALIZER_H
29
30 #include "Exception.h"
31 #include "details.h"
32
33 #include <cstdint>
34 #include <string>
35 #include <type_traits>
36 #include <vector>
37
38 namespace PdCom {
39 /** Data Deserialisation helper.
40 *
41 * This class is used to extract the values from the buffer
42 * as requested by the library user.
43 * It is expected that Derived has at least a getData() member
44 * which returns a pointer to the buffer and a getVariable()
45 * member which returns the corresponding variable.
46 *
47 */
48
49 template <class Derived>
50 struct DataDeserializer
51 {
52 /** Copy the values into a custom buffer.
53 *
54 * Up to \p buf.size() values are converted into the type of the buffer.
55 * This overload accepts a container like \c std::vector , but also
56 * non-contiguous containers like \c std::list are supported.
57 * A member typedef \c value_type and a size() member are expected.
58 *
59 * \param dest Custom buffer.
60 */
61 template <typename T>
62 typename std::enable_if<!std::is_arithmetic<T>::value, void>::type
63 getValue(T &dest, size_t offset = 0) const;
64
65 /** Copy the values into a custom buffer.
66 *
67 * \param dest Custom buffer.
68 */
69 template <typename T>
70 typename std::enable_if<std::is_arithmetic<T>::value, void>::type
71 56 getValue(T &dest, size_t offset = 0) const
72 {
73
7/14
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 26 taken 12 times.
✗ Branch 27 not taken.
✓ Branch 40 taken 3 times.
✗ Branch 41 not taken.
✓ Branch 48 taken 15 times.
✗ Branch 49 not taken.
✓ Branch 56 taken 18 times.
✗ Branch 57 not taken.
112 const auto var = static_cast<const Derived &>(*this).getVariable();
74
8/16
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 26 taken 12 times.
✗ Branch 27 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 42 taken 3 times.
✗ Branch 43 not taken.
✓ Branch 50 taken 15 times.
✗ Branch 51 not taken.
✓ Branch 58 taken 18 times.
✗ Branch 59 not taken.
56 const auto total_elements = var.getSizeInfo().totalElements();
75
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 15 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 18 times.
56 if (offset >= total_elements)
76 throw InvalidArgument(
77 "offset too large, must be less than "
78 + std::to_string(total_elements));
79
23/46
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 12 times.
✓ Branch 35 taken 12 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 12 times.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 1 times.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 3 times.
✓ Branch 53 taken 3 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 3 times.
✗ Branch 57 not taken.
✗ Branch 59 not taken.
✓ Branch 60 taken 15 times.
✓ Branch 63 taken 15 times.
✗ Branch 64 not taken.
✓ Branch 66 taken 15 times.
✗ Branch 67 not taken.
✗ Branch 69 not taken.
✓ Branch 70 taken 18 times.
✓ Branch 73 taken 18 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 18 times.
✗ Branch 77 not taken.
168 details::copyData(
80 56 &dest, details::TypeInfoTraits<T>::type_info.type,
81 static_cast<const Derived &>(*this).getData(),
82
8/16
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 17 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 26 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 31 taken 15 times.
✗ Branch 32 not taken.
✓ Branch 36 taken 18 times.
✗ Branch 37 not taken.
112 var.getTypeInfo().type, 1, offset);
83 56 }
84
85 template <typename T, size_t M, size_t N>
86 2 void getValue(T (&dest)[M][N]) const
87 {
88
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 const auto var = static_cast<const Derived &>(*this).getVariable();
89
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
2 if (var.getSizeInfo().totalElements() != M * N)
90 throw InvalidArgument(
91 "Size mismatch between destination and source");
92
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
6 details::copyData(
93 2 dest, details::TypeInfoTraits<T>::type_info.type,
94 static_cast<const Derived &>(*this).getData(),
95
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 var.getTypeInfo().type, M * N);
96 2 }
97 template <typename T, size_t N>
98 2 void getValue(T (&dest)[N], size_t offset = 0) const
99 {
100
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 const auto var = static_cast<const Derived &>(*this).getVariable();
101
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 const auto total_elements = var.getSizeInfo().totalElements();
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset >= total_elements)
103 throw InvalidArgument(
104 "offset too large, must be less than "
105 + std::to_string(total_elements));
106
3/6
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
6 details::copyData(
107 2 dest, details::TypeInfoTraits<T>::type_info.type,
108 static_cast<const Derived &>(*this).getData(),
109
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 var.getTypeInfo().type,
110 4 std::min<size_t>(N, total_elements - offset), offset);
111 2 }
112 template <typename T>
113 6 T getValue() const
114 {
115 6 T ans;
116
4/8
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
6 this->getValue(ans);
117 6 return ans;
118 }
119 };
120
121 template <class Derived>
122 template <typename T>
123 inline typename std::enable_if<!std::is_arithmetic<T>::value, void>::type
124 16 DataDeserializer<Derived>::getValue(T &dest, size_t offset) const
125 {
126
4/8
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 26 taken 9 times.
✗ Branch 27 not taken.
32 const auto var = static_cast<const Derived &>(*this).getVariable();
127
4/8
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 26 taken 9 times.
✗ Branch 27 not taken.
16 const auto total_elements = var.getSizeInfo().totalElements();
128 static_assert(
129 std::is_same<
130 decltype(dest[0]),
131 typename std::add_lvalue_reference<
132 typename T::value_type>::type>::value,
133 "Index operator does not return a lvalue reference of an "
134 "integral");
135
5/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
16 if (offset >= total_elements)
136
1/8
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1 throw InvalidArgument("Offset too large");
137 15 const auto count = std::min<size_t>(dest.size(), total_elements - offset);
138
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
15 const auto src_type = var.getTypeInfo();
139 15 const auto dst_type =
140 details::TypeInfoTraits<typename T::value_type>::type_info.type;
141
142
4/8
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 9 times.
✗ Branch 15 not taken.
15 const auto src = static_cast<const Derived &>(*this).getData();
143 if (!details::is_contiguous<T>::value) {
144
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (unsigned int i = 0; i < count; ++i) {
145
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 details::copyData(
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 &dest[i], dst_type, src, src_type.type, 1, offset + i);
147 }
148 }
149 else {
150
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
14 details::copyData(
151
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 9 times.
14 &dest[0], dst_type, src, src_type.type, count, offset);
152 }
153 15 }
154
155 } // namespace PdCom
156
157
158 #endif // PDCOM5_DATADESERIALIZER_H
159