GCC Code Coverage Report


Directory: ./
File: pdcom5/src/msrproto/DataConverter.h
Date: 2024-11-17 04:08:36
Exec Total Coverage
Lines: 35 38 92.1%
Branches: 29 52 55.8%

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 #ifndef PDCOM5_MSRPROTO_DATADECODER_H
25 #define PDCOM5_MSRPROTO_DATADECODER_H
26
27 #include <cstddef>
28 #include <cstring>
29 #include <memory>
30 #include <ostream>
31 #include <pdcom5/Exception.h>
32 #include <pdcom5/SizeTypeInfo.h>
33 #include <unordered_map>
34 #include <vector>
35
36 namespace PdCom { namespace impl { namespace MsrProto {
37
38 class Variable;
39 class XmlStream;
40
41 146 struct DataDecoder : std::vector<char>
42 {
43 void readFromHexDec(
44 const char *s,
45 const Variable &var,
46 unsigned int blocksize = 1);
47 void readFromString(
48 const char *s,
49 const Variable &var,
50 unsigned int blocksize = 1);
51 void readFromBase64(
52 const char *s,
53 const size_t base64length_,
54 const Variable &var,
55 unsigned int blocksize = 1);
56 };
57
58 313 class DataEncoder
59 {
60 std::vector<unsigned char> converted_value_;
61
62 public:
63 void
64 toHex(TypeInfo const &dst_type,
65 const void *src,
66 TypeInfo::DataType src_type,
67 size_t n,
68 XmlStream &os);
69 };
70
71 struct Base64Info
72 {
73 547 explicit Base64Info(const char *data)
74 547 {
75
2/4
✓ Branch 0 taken 547 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 547 times.
547 if (!data || !*data)
76 throw PdCom::ProtocolError("Tag does not contain data");
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 547 times.
547 base64Length_ = ::strlen(data);
78
79
3/6
✓ Branch 1 taken 547 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 547 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 547 times.
547 if (base64Length_ < 4 || (base64Length_ % 4) != 0)
80 throw PdCom::ProtocolError("Invalid base64 data tag");
81 547 encodedDataLength_ = base64Length_ * 3 / 4;
82
83
1/2
✓ Branch 2 taken 547 times.
✗ Branch 3 not taken.
547 if (data[base64Length_ - 1] == '=')
84 547 --encodedDataLength_;
85
2/2
✓ Branch 2 taken 336 times.
✓ Branch 3 taken 211 times.
547 if (data[base64Length_ - 2] == '=')
86 336 --encodedDataLength_;
87 547 }
88
89 size_t base64Length_, encodedDataLength_;
90 };
91
92 // len(dst) must be
93 bool readFromBase64(
94 char *dst,
95 const char *src,
96 const size_t base64length_,
97 size_t buflen);
98
99 313 class VariableCache
100 {
101 using InternalType = std::unordered_map<unsigned int, DataDecoder>;
102 InternalType cache_;
103 bool locked_ = false;
104
105 struct Unlocker
106 {
107 434 void operator()(VariableCache *vc) const
108 {
109
1/2
✓ Branch 0 taken 434 times.
✗ Branch 1 not taken.
434 if (vc) {
110
2/2
✓ Branch 6 taken 630 times.
✓ Branch 7 taken 434 times.
1064 for (auto &kv : vc->cache_)
111
1/2
✓ Branch 2 taken 630 times.
✗ Branch 3 not taken.
630 kv.second.resize(0);
112 434 vc->locked_ = false;
113 }
114 434 }
115 };
116
117 public:
118 4803 struct Lock
119 {
120 std::unique_ptr<VariableCache, Unlocker> cache_ptr_;
121
122 974 Lock(VariableCache *vc = nullptr) : cache_ptr_(vc) {}
123
124 383 operator bool() const { return static_cast<bool>(cache_ptr_); }
125
126 648 DataDecoder &operator[](unsigned int idx)
127 {
128 648 return cache_ptr_->cache_[idx];
129 }
130 1245 const DataDecoder *filled_cache(unsigned int idx) const
131 {
132
1/2
✓ Branch 2 taken 1245 times.
✗ Branch 3 not taken.
1245 if (cache_ptr_) {
133
3/4
✓ Branch 4 taken 1245 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 35 times.
✓ Branch 8 taken 1210 times.
1280 const auto it = cache_ptr_->cache_.find(idx);
134
8/10
✓ Branch 6 taken 1240 times.
✓ Branch 7 taken 5 times.
✓ Branch 11 taken 1210 times.
✓ Branch 12 taken 30 times.
✓ Branch 13 taken 1245 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1245 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1210 times.
✓ Branch 20 taken 35 times.
1245 if (it != cache_ptr_->cache_.end() and it->second.size() > 0)
135
2/2
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 1210 times.
1210 return &it->second;
136 }
137 35 return nullptr;
138 }
139 };
140
141 434 Lock lock()
142 {
143
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 434 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 434 times.
434 if (locked_)
144 throw InternalError("Variable Cache is in use!");
145 434 locked_ = true;
146 434 return Lock {this};
147 }
148 };
149
150 }}} // namespace PdCom::impl::MsrProto
151
152
153 #endif // PDCOM5_MSRPROTO_DATADECODER_H
154