monotone

monotone Mtn Source Tree

Root/botan/pipe.cpp

1/*************************************************
2* Pipe Source File *
3* (C) 1999-2007 The Botan Project *
4*************************************************/
5
6#include <botan/pipe.h>
7#include <botan/out_buf.h>
8#include <botan/secqueue.h>
9
10namespace Botan {
11
12namespace {
13
14/*************************************************
15* A Filter that does nothing *
16*************************************************/
17class Null_Filter : public Filter
18 {
19 public:
20 void write(const byte input[], u32bit length)
21 { send(input, length); }
22 };
23
24}
25
26/*************************************************
27* Pipe Constructor *
28*************************************************/
29Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4)
30 {
31 init();
32 append(f1);
33 append(f2);
34 append(f3);
35 append(f4);
36 }
37
38/*************************************************
39* Pipe Constructor *
40*************************************************/
41Pipe::Pipe(Filter* filter_array[], u32bit count)
42 {
43 init();
44 for(u32bit j = 0; j != count; ++j)
45 append(filter_array[j]);
46 }
47
48/*************************************************
49* Pipe Destructor *
50*************************************************/
51Pipe::~Pipe()
52 {
53 destruct(pipe);
54 delete outputs;
55 }
56
57/*************************************************
58* Initialize the Pipe *
59*************************************************/
60void Pipe::init()
61 {
62 outputs = new Output_Buffers;
63 pipe = 0;
64 default_read = 0;
65 inside_msg = false;
66 }
67
68/*************************************************
69* Reset the Pipe *
70*************************************************/
71void Pipe::reset()
72 {
73 if(inside_msg)
74 throw Invalid_State("Pipe cannot be reset while it is processing");
75 destruct(pipe);
76 pipe = 0;
77 inside_msg = false;
78 }
79
80/*************************************************
81* Destroy the Pipe *
82*************************************************/
83void Pipe::destruct(Filter* to_kill)
84 {
85 if(!to_kill || dynamic_cast<SecureQueue*>(to_kill))
86 return;
87 for(u32bit j = 0; j != to_kill->total_ports(); ++j)
88 destruct(to_kill->next[j]);
89 delete to_kill;
90 }
91
92/*************************************************
93* Test if the Pipe has any data in it *
94*************************************************/
95bool Pipe::end_of_data() const
96 {
97 return (remaining() == 0);
98 }
99
100/*************************************************
101* Set the default read message *
102*************************************************/
103void Pipe::set_default_msg(u32bit msg)
104 {
105 if(msg >= message_count())
106 throw Invalid_Argument("Pipe::set_default_msg: msg number is too high");
107 default_read = msg;
108 }
109
110/*************************************************
111* Process a full message at once *
112*************************************************/
113void Pipe::process_msg(const byte input[], u32bit length)
114 {
115 start_msg();
116 write(input, length);
117 end_msg();
118 }
119
120/*************************************************
121* Process a full message at once *
122*************************************************/
123void Pipe::process_msg(const MemoryRegion<byte>& input)
124 {
125 process_msg(input.begin(), input.size());
126 }
127
128/*************************************************
129* Process a full message at once *
130*************************************************/
131void Pipe::process_msg(const std::string& input)
132 {
133 process_msg(reinterpret_cast<const byte*>(input.data()), input.length());
134 }
135
136/*************************************************
137* Process a full message at once *
138*************************************************/
139void Pipe::process_msg(DataSource& input)
140 {
141 start_msg();
142 write(input);
143 end_msg();
144 }
145
146/*************************************************
147* Start a new message *
148*************************************************/
149void Pipe::start_msg()
150 {
151 if(inside_msg)
152 throw Invalid_State("Pipe::start_msg: Message was already started");
153 if(pipe == 0)
154 pipe = new Null_Filter;
155 find_endpoints(pipe);
156 pipe->new_msg();
157 inside_msg = true;
158 }
159
160/*************************************************
161* End the current message *
162*************************************************/
163void Pipe::end_msg()
164 {
165 if(!inside_msg)
166 throw Invalid_State("Pipe::end_msg: Message was already ended");
167 pipe->finish_msg();
168 clear_endpoints(pipe);
169 if(dynamic_cast<Null_Filter*>(pipe))
170 {
171 delete pipe;
172 pipe = 0;
173 }
174 inside_msg = false;
175
176 outputs->retire();
177 }
178
179/*************************************************
180* Find the endpoints of the Pipe *
181*************************************************/
182void Pipe::find_endpoints(Filter* f)
183 {
184 for(u32bit j = 0; j != f->total_ports(); ++j)
185 if(f->next[j] && !dynamic_cast<SecureQueue*>(f->next[j]))
186 find_endpoints(f->next[j]);
187 else
188 {
189 SecureQueue* q = new SecureQueue;
190 f->next[j] = q;
191 outputs->add(q);
192 }
193 }
194
195/*************************************************
196* Remove the SecureQueues attached to the Filter *
197*************************************************/
198void Pipe::clear_endpoints(Filter* f)
199 {
200 if(!f) return;
201 for(u32bit j = 0; j != f->total_ports(); ++j)
202 {
203 if(f->next[j] && dynamic_cast<SecureQueue*>(f->next[j]))
204 f->next[j] = 0;
205 clear_endpoints(f->next[j]);
206 }
207 }
208
209/*************************************************
210* Append a Filter to the Pipe *
211*************************************************/
212void Pipe::append(Filter* filter)
213 {
214 if(inside_msg)
215 throw Invalid_State("Cannot append to a Pipe while it is processing");
216 if(!filter)
217 return;
218 if(dynamic_cast<SecureQueue*>(filter))
219 throw Invalid_Argument("Pipe::append: SecureQueue cannot be used");
220 if(filter->owned)
221 throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
222
223 filter->owned = true;
224
225 if(!pipe) pipe = filter;
226 else pipe->attach(filter);
227 }
228
229/*************************************************
230* Prepend a Filter to the Pipe *
231*************************************************/
232void Pipe::prepend(Filter* filter)
233 {
234 if(inside_msg)
235 throw Invalid_State("Cannot prepend to a Pipe while it is processing");
236 if(!filter)
237 return;
238 if(dynamic_cast<SecureQueue*>(filter))
239 throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used");
240 if(filter->owned)
241 throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
242
243 filter->owned = true;
244
245 if(pipe) filter->attach(pipe);
246 pipe = filter;
247 }
248
249/*************************************************
250* Pop a Filter off the Pipe *
251*************************************************/
252void Pipe::pop()
253 {
254 if(inside_msg)
255 throw Invalid_State("Cannot pop off a Pipe while it is processing");
256
257 if(!pipe)
258 return;
259
260 if(pipe->total_ports() > 1)
261 throw Invalid_State("Cannot pop off a Filter with multiple ports");
262
263 Filter* f = pipe;
264 u32bit owns = f->owns();
265 pipe = pipe->next[0];
266 delete f;
267
268 while(owns--)
269 {
270 f = pipe;
271 pipe = pipe->next[0];
272 delete f;
273 }
274 }
275
276/*************************************************
277* Return the number of messages in this Pipe *
278*************************************************/
279u32bit Pipe::message_count() const
280 {
281 return outputs->message_count();
282 }
283
284/*************************************************
285* Static Member Variables *
286*************************************************/
287const u32bit Pipe::LAST_MESSAGE = 0xFFFFFFFE;
288const u32bit Pipe::DEFAULT_MESSAGE = 0xFFFFFFFF;
289
290}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status