• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 16249365818

13 Jul 2025 12:56PM UTC coverage: 90.618% (+0.002%) from 90.616%
16249365818

Pull #4985

github

web-flow
Merge 34acb0b10 into cf74a5db8
Pull Request #4985: Enable and fix clang-tidy warning cppcoreguidelines-prefer-member-initializer

99527 of 109831 relevant lines covered (90.62%)

12274327.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.53
/src/lib/filters/pipe.cpp
1
/*
2
* Pipe
3
* (C) 1999-2007 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/pipe.h>
9

10
#include <botan/mem_ops.h>
11
#include <botan/internal/fmt.h>
12
#include <botan/internal/out_buf.h>
13
#include <botan/internal/secqueue.h>
14
#include <memory>
15

16
namespace Botan {
17

18
namespace {
19

20
/*
21
* A Filter that does nothing
22
*/
23
class Null_Filter final : public Filter {
4✔
24
   public:
25
      void write(const uint8_t input[], size_t length) override { send(input, length); }
1✔
26

27
      std::string name() const override { return "Null"; }
×
28
};
29

30
}  // namespace
31

32
Pipe::Pipe(Pipe&&) noexcept = default;
×
33

34
Pipe::Invalid_Message_Number::Invalid_Message_Number(std::string_view where, message_id msg) :
1✔
35
      Invalid_Argument(fmt("Pipe::{}: Invalid message number {}", where, msg)) {}
2✔
36

37
/*
38
* Pipe Constructor
39
*/
40
Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) : Pipe({f1, f2, f3, f4}) {}
18✔
41

42
/*
43
* Pipe Constructor
44
*/
45
Pipe::Pipe(std::initializer_list<Filter*> args) : m_pipe(nullptr), m_default_read(0), m_inside_msg(false) {
18✔
46
   m_outputs = std::make_unique<Output_Buffers>();
18✔
47

48
   for(auto* arg : args) {
90✔
49
      do_append(arg);
72✔
50
   }
51
}
18✔
52

53
/*
54
* Pipe Destructor
55
*/
56
Pipe::~Pipe() {
18✔
57
   destruct(m_pipe);
18✔
58
}
18✔
59

60
/*
61
* Reset the Pipe
62
*/
63
void Pipe::reset() {
6✔
64
   destruct(m_pipe);
6✔
65
   m_pipe = nullptr;
6✔
66
   m_inside_msg = false;
6✔
67
}
6✔
68

69
/*
70
* Destroy the Pipe
71
*/
72
void Pipe::destruct(Filter* to_kill) {
80✔
73
   if(to_kill == nullptr) {
80✔
74
      return;
75
   }
76

77
   if(dynamic_cast<SecureQueue*>(to_kill) != nullptr) {
49✔
78
      return;
79
   }
80

81
   for(size_t j = 0; j != to_kill->total_ports(); ++j) {
105✔
82
      destruct(to_kill->m_next[j]);
56✔
83
   }
84
   delete to_kill;  // NOLINT(*owning-memory)
49✔
85
}
86

87
/*
88
* Test if the Pipe has any data in it
89
*/
90
bool Pipe::end_of_data() const {
2✔
91
   return (remaining() == 0);
2✔
92
}
93

94
/*
95
* Set the default read message
96
*/
97
void Pipe::set_default_msg(message_id msg) {
3✔
98
   if(msg >= message_count()) {
3✔
99
      throw Invalid_Argument("Pipe::set_default_msg: msg number is too high");
×
100
   }
101
   m_default_read = msg;
3✔
102
}
3✔
103

104
/*
105
* Process a full message at once
106
*/
107
void Pipe::process_msg(const uint8_t input[], size_t length) {
39✔
108
   start_msg();
39✔
109
   write(input, length);
39✔
110
   end_msg();
39✔
111
}
39✔
112

113
/*
114
* Process a full message at once
115
*/
116
void Pipe::process_msg(const secure_vector<uint8_t>& input) {
2✔
117
   process_msg(input.data(), input.size());
2✔
118
}
2✔
119

120
void Pipe::process_msg(const std::vector<uint8_t>& input) {
1✔
121
   process_msg(input.data(), input.size());
1✔
122
}
1✔
123

124
/*
125
* Process a full message at once
126
*/
127
void Pipe::process_msg(std::string_view input) {
36✔
128
   process_msg(cast_char_ptr_to_uint8(input.data()), input.length());
36✔
129
}
36✔
130

131
/*
132
* Process a full message at once
133
*/
134
void Pipe::process_msg(DataSource& input) {
4✔
135
   start_msg();
4✔
136
   write(input);
4✔
137
   end_msg();
4✔
138
}
4✔
139

140
/*
141
* Start a new message
142
*/
143
void Pipe::start_msg() {
65✔
144
   if(m_inside_msg) {
65✔
145
      throw Invalid_State("Pipe::start_msg: Message was already started");
×
146
   }
147
   if(m_pipe == nullptr) {
65✔
148
      m_pipe = new Null_Filter;  // NOLINT(*-owning-memory)
2✔
149
   }
150
   find_endpoints(m_pipe);
65✔
151
   m_pipe->new_msg();
65✔
152
   m_inside_msg = true;
65✔
153
}
65✔
154

155
/*
156
* End the current message
157
*/
158
void Pipe::end_msg() {
65✔
159
   if(!m_inside_msg) {
65✔
160
      throw Invalid_State("Pipe::end_msg: Message was already ended");
×
161
   }
162
   m_pipe->finish_msg();
65✔
163
   clear_endpoints(m_pipe);
65✔
164
   if(dynamic_cast<Null_Filter*>(m_pipe) != nullptr) {
65✔
165
      delete m_pipe;
2✔
166
      m_pipe = nullptr;
2✔
167
   }
168
   m_inside_msg = false;
65✔
169

170
   m_outputs->retire();
65✔
171
}
65✔
172

173
/*
174
* Find the endpoints of the Pipe
175
*/
176
void Pipe::find_endpoints(Filter* f) {
135✔
177
   for(size_t j = 0; j != f->total_ports(); ++j) {
277✔
178
      if(f->m_next[j] != nullptr && dynamic_cast<SecureQueue*>(f->m_next[j]) == nullptr) {
142✔
179
         find_endpoints(f->m_next[j]);
70✔
180
      } else {
181
         SecureQueue* q = new SecureQueue;  // NOLINT(*-owning-memory)
72✔
182
         f->m_next[j] = q;
72✔
183
         m_outputs->add(q);
72✔
184
      }
185
   }
186
}
135✔
187

188
/*
189
* Remove the SecureQueues attached to the Filter
190
*/
191
void Pipe::clear_endpoints(Filter* f) {
207✔
192
   if(!f) {
207✔
193
      return;
194
   }
195
   for(size_t j = 0; j != f->total_ports(); ++j) {
277✔
196
      if(f->m_next[j] && dynamic_cast<SecureQueue*>(f->m_next[j])) {
142✔
197
         f->m_next[j] = nullptr;
72✔
198
      }
199
      clear_endpoints(f->m_next[j]);
142✔
200
   }
201
}
202

203
void Pipe::append(Filter* filter) {
19✔
204
   do_append(filter);
19✔
205
}
17✔
206

207
void Pipe::append_filter(Filter* filter) {
4✔
208
   if(m_outputs->message_count() != 0) {
4✔
209
      throw Invalid_State("Cannot call Pipe::append_filter after start_msg");
2✔
210
   }
211

212
   do_append(filter);
2✔
213
}
2✔
214

215
void Pipe::prepend(Filter* filter) {
5✔
216
   do_prepend(filter);
5✔
217
}
3✔
218

219
void Pipe::prepend_filter(Filter* filter) {
4✔
220
   if(m_outputs->message_count() != 0) {
4✔
221
      throw Invalid_State("Cannot call Pipe::prepend_filter after start_msg");
2✔
222
   }
223

224
   do_prepend(filter);
2✔
225
}
2✔
226

227
/*
228
* Append a Filter to the Pipe
229
*/
230
void Pipe::do_append(Filter* filter) {
93✔
231
   if(!filter) {
93✔
232
      return;
233
   }
234
   if(dynamic_cast<SecureQueue*>(filter)) {
41✔
235
      throw Invalid_Argument("Pipe::append: SecureQueue cannot be used");
1✔
236
   }
237
   if(filter->m_owned) {
40✔
238
      throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
×
239
   }
240

241
   if(m_inside_msg) {
40✔
242
      throw Invalid_State("Cannot append to a Pipe while it is processing");
1✔
243
   }
244

245
   filter->m_owned = true;
39✔
246

247
   if(!m_pipe) {
39✔
248
      m_pipe = filter;
25✔
249
   } else {
250
      m_pipe->attach(filter);
14✔
251
   }
252
}
253

254
/*
255
* Prepend a Filter to the Pipe
256
*/
257
void Pipe::do_prepend(Filter* filter) {
7✔
258
   if(m_inside_msg) {
7✔
259
      throw Invalid_State("Cannot prepend to a Pipe while it is processing");
1✔
260
   }
261
   if(!filter) {
6✔
262
      return;
263
   }
264
   if(dynamic_cast<SecureQueue*>(filter)) {
3✔
265
      throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used");
1✔
266
   }
267
   if(filter->m_owned) {
2✔
268
      throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
×
269
   }
270

271
   filter->m_owned = true;
2✔
272

273
   if(m_pipe) {
2✔
274
      filter->attach(m_pipe);
×
275
   }
276
   m_pipe = filter;
2✔
277
}
278

279
/*
280
* Pop a Filter off the Pipe
281
*/
282
void Pipe::pop() {
10✔
283
   if(m_inside_msg) {
10✔
284
      throw Invalid_State("Cannot pop off a Pipe while it is processing");
1✔
285
   }
286

287
   if(!m_pipe) {
9✔
288
      return;
289
   }
290

291
   if(m_pipe->total_ports() > 1) {
7✔
292
      throw Invalid_State("Cannot pop off a Filter with multiple ports");
×
293
   }
294

295
   size_t to_remove = m_pipe->owns() + 1;
7✔
296

297
   while(to_remove--) {
16✔
298
      std::unique_ptr<Filter> to_destroy(m_pipe);
9✔
299
      m_pipe = m_pipe->m_next[0];
9✔
300
   }
9✔
301
}
302

303
/*
304
* Return the number of messages in this Pipe
305
*/
306
Pipe::message_id Pipe::message_count() const {
243✔
307
   return m_outputs->message_count();
243✔
308
}
309

310
/*
311
* Static Member Variables
312
*/
313
const Pipe::message_id Pipe::LAST_MESSAGE = static_cast<Pipe::message_id>(-2);
314

315
const Pipe::message_id Pipe::DEFAULT_MESSAGE = static_cast<Pipe::message_id>(-1);
316

317
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc