Packet.cti
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief Packet inline template implementation */
16 
17 //#include "Packet.ih"
18 
19 // Custom includes
20 #include <senf/Utils/Exception.hh>
21 #include <senf/Utils/senflikely.hh>
22 
23 #define prefix_ inline
24 //-/////////////////////////////////////////////////////////////////////////////////////////////////
25 
26 //-/////////////////////////////////////////////////////////////////////////////////////////////////
27 // senf::Packet
28 
29 // conversion constructors
30 
31 template <class PacketType>
32 prefix_ senf::Packet::Packet(ConcretePacket<PacketType> const & packet)
33  : packet_(packet.ptr())
34 {
35 #ifdef SENF_DEBUG
36  pktCount_++;
37 #endif
38 }
39 
40 // interpreter chain access
41 
42 template <class OtherPacket>
43 prefix_ OtherPacket senf::Packet::parseNextAs()
44  const
45 {
46  return OtherPacket(ptr()->parseNextAs<typename OtherPacket::type>());
47 }
48 
49 template <class OtherPacket>
50 prefix_ bool senf::Packet::is()
51  const
52 {
53  // ensure that the template class is included in the corresponding object file when linking:
54  { static typename PacketInterpreter<typename OtherPacket::type>::factory_t _ (
55  PacketInterpreter<typename OtherPacket::type>::factory()); (void) _;}
56  return (*this) && typeId() == typeIdValue<OtherPacket>();
57 }
58 
59 template <class OtherPacket>
60 prefix_ OtherPacket const & senf::Packet::as()
61  const
62 {
63  if (SENF_UNLIKELY(!is<OtherPacket>()))
64  throw make_WrapException(std::bad_cast())
65  << ": called packet::as() with wrong PacketType: "
66  << ((*this) ? typeId().prettyName() : "invalid packet")
67  << " != " << prettyName(typeid(OtherPacket));
68  // The following cast is safe since OtherPacket inherits from Packet with single inheritance
69  // and does not change the class layout (it does not add any virtual members and has no
70  // data members)
71  return static_cast<OtherPacket const &>(*this);
72 }
73 
74 template <class OtherPacket>
75 prefix_ OtherPacket & senf::Packet::as()
76 {
77  if (SENF_UNLIKELY(!is<OtherPacket>()))
78  throw make_WrapException(std::bad_cast())
79  << ": called packet::as() with wrong PacketType: "
80  << ((*this) ? typeId().prettyName() : "invalid packet")
81  << " != " << prettyName(typeid(OtherPacket));
82  // The following cast is safe since OtherPacket inherits from Packet with single inheritance
83  // and does not change the class layout (it does not add any virtual members and has no
84  // data members)
85  return static_cast<OtherPacket &>(*this);
86 }
87 
88 template <class OtherPacket>
89 prefix_ OtherPacket const & senf::Packet::as(NoThrow_t)
90  const
91 {
92  SENF_ASSERT( is<OtherPacket>(), "Bad cast, called packet::as(nothrow) with wrong PacketType");
93  // The following cast is safe since OtherPacket inherits from Packet with single inheritance
94  // and does not change the class layout (it does not add any virtual members and has no
95  // data members)
96  return static_cast<OtherPacket const &>(*this);
97 }
98 
99 template <class OtherPacket>
100 prefix_ OtherPacket & senf::Packet::as(NoThrow_t)
101 {
102  SENF_ASSERT( is<OtherPacket>(), "Bad cast, called packet::as(nothrow) with wrong PacketType");
103  // The following cast is safe since OtherPacket inherits from Packet with single inheritance
104  // and does not change the class layout (it does not add any virtual members and has no
105  // data members)
106  return static_cast<OtherPacket &>(*this);
107 }
108 
109 template <class OtherPacket>
110 prefix_ OtherPacket senf::Packet::next()
111  const
112 {
113  return next().as<OtherPacket>();
114 }
115 
116 template <class OtherPacket>
117 prefix_ OtherPacket senf::Packet::next(NoThrow_t)
118  const
119 {
120  Packet p (next(nothrow));
121  return SENF_LIKELY(p && p.is<OtherPacket>()) ?
122  OtherPacket(p.ptr()->as<typename OtherPacket::type>()) : OtherPacket();
123 }
124 
125 template <class OtherPacket>
126 prefix_ OtherPacket senf::Packet::find()
127  const
128 {
129  OtherPacket p (find<OtherPacket>(nothrow));
130  if (!p) throw InvalidPacketChainException();
131  return p;
132 }
133 
134 template <class OtherPacket>
135 prefix_ OtherPacket senf::Packet::prev()
136  const
137 {
138  return prev().as<OtherPacket>();
139 }
140 
141 template <class OtherPacket>
142 prefix_ OtherPacket senf::Packet::prev(NoThrow_t)
143  const
144 {
145  Packet p (prev(nothrow));
146  return p && p.is<OtherPacket>() ?
147  OtherPacket(p.ptr()->as<typename OtherPacket::type>()) : OtherPacket();
148 }
149 
150 template <class OtherPacket>
151 prefix_ OtherPacket senf::Packet::rfind()
152  const
153 {
154  OtherPacket p (rfind<OtherPacket>(nothrow));
155  if (!p) throw InvalidPacketChainException();
156  return p;
157 }
158 
159 template <class OtherPacket>
160 prefix_ OtherPacket senf::Packet::last()
161  const
162 {
163  return last().as<OtherPacket>();
164 }
165 
166 template <class OtherPacket>
167 prefix_ OtherPacket senf::Packet::first()
168  const
169 {
170  return first().as<OtherPacket>();
171 }
172 
173 template <class Other>
174 prefix_ void senf::Packet::finalizeTo()
175 {
176  Packet p (find<Other>(nothrow));
177  ptr()->finalizeTo(p ? p.ptr() : last().ptr());
178 }
179 
180 template <class Annotation>
181 prefix_ Annotation & senf::Packet::annotation()
182 {
183  return ptr()->annotation<Annotation>();
184 }
185 
186 template <class Annotation>
187 prefix_ Annotation const & senf::Packet::annotation()
188  const
189 {
190  return ptr()->annotation<Annotation>();
191 }
192 
193 template <class OtherPacket>
194 prefix_ OtherPacket senf::Packet::replaceAs(difference_type offset, difference_type tailOffset)
195 {
196  OtherPacket res (ptr()->replaceAs<typename OtherPacket::type>(offset, tailOffset));
197  packet_.reset();
198  return res;
199 }
200 
201 template <class PacketType, class Parser>
202 prefix_ Parser senf::operator<<(Parser target, ConcretePacket<PacketType> const & packet)
203 {
204  target << packet.parser();
205  return target;
206 }
207 
208 //-/////////////////////////////////////////////////////////////////////////////////////////////////
209 // senf::ConcretePacket<PacketType>
210 
211 // structors and default members
212 
213 template <class PacketType>
214 prefix_ senf::ConcretePacket<PacketType>::ConcretePacket()
215  : Packet()
216 {}
217 
218 template <class PacketType>
219 prefix_ typename senf::ConcretePacket<PacketType>::factory_t
220 senf::ConcretePacket<PacketType>::factory()
221 {
222  return interpreter::factory();
223 }
224 
225 // Create completely new packet
226 
227 template <class PacketType>
228 prefix_ senf::ConcretePacket<PacketType>
229 senf::ConcretePacket<PacketType>::create()
230 {
231  return ConcretePacket(interpreter::create());
232 }
233 
234 template <class PacketType>
235 prefix_ senf::ConcretePacket<PacketType>
236 senf::ConcretePacket<PacketType>::create(senf::NoInit_t)
237 {
238  return ConcretePacket(interpreter::create(senf::noinit));
239 }
240 
241 template <class PacketType>
242 prefix_ senf::ConcretePacket<PacketType>
243 senf::ConcretePacket<PacketType>::create(size_type size)
244 {
245  return ConcretePacket(interpreter::create(size));
246 }
247 
248 template <class PacketType>
249 prefix_ senf::ConcretePacket<PacketType>
250 senf::ConcretePacket<PacketType>::create(size_type size, senf::NoInit_t)
251 {
252  return ConcretePacket(interpreter::create(size,senf::noinit));
253 }
254 
255 #ifndef DOXYGEN
256 
257 template <class PacketType>
258 template <class ForwardReadableRange>
259 prefix_ senf::ConcretePacket<PacketType> senf::ConcretePacket<PacketType>::
260 create(ForwardReadableRange const & range,
261  typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type *)
262 {
263  return ConcretePacket(interpreter::create(range));
264 }
265 
266 #endif
267 
268 template <class PacketType>
269 prefix_ senf::ConcretePacket<PacketType>
270 senf::ConcretePacket<PacketType>::create(byte * data, size_type size, size_type chunkSize,
271  size_type offset)
272 {
273  return ConcretePacket(interpreter::create(data, size, chunkSize, offset));
274 }
275 
276 // Create packet as new packet after a given packet
277 
278 template <class PacketType>
279 prefix_ senf::ConcretePacket<PacketType>
280 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet)
281 {
282  return ConcretePacket(interpreter::createAfter(packet.ptr()));
283 }
284 
285 template <class PacketType>
286 prefix_ senf::ConcretePacket<PacketType>
287 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, senf::NoInit_t)
288 {
289  return ConcretePacket(interpreter::createAfter(packet.ptr(),senf::noinit));
290 }
291 
292 template <class PacketType>
293 prefix_ senf::ConcretePacket<PacketType>
294 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size)
295 {
296  return ConcretePacket(interpreter::createAfter(packet.ptr(), size));
297 }
298 
299 template <class PacketType>
300 prefix_ senf::ConcretePacket<PacketType>
301 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size,
302  senf::NoInit_t)
303 {
304  return ConcretePacket(interpreter::createAfter(packet.ptr(), size, senf::noinit));
305 }
306 
307 #ifndef DOXYGEN
308 
309 template <class PacketType>
310 template <class ForwardReadableRange>
311 prefix_ senf::ConcretePacket<PacketType> senf::ConcretePacket<PacketType>::
312 createAfter(Packet const & packet, ForwardReadableRange const & range,
313  typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type *)
314 {
315  return ConcretePacket(interpreter::createAfter(packet.ptr(), range));
316 }
317 
318 #endif
319 
320 // Create packet as new packet (header) before a given packet
321 
322 template <class PacketType>
323 prefix_ senf::ConcretePacket<PacketType>
324 senf::ConcretePacket<PacketType>::createBefore(Packet const & packet)
325 {
326  return ConcretePacket(interpreter::createBefore(packet.ptr()));
327 }
328 
329 template <class PacketType>
330 prefix_ senf::ConcretePacket<PacketType>
331 senf::ConcretePacket<PacketType>::createBeforeNoZero(Packet const & packet)
332 {
333  return ConcretePacket(interpreter::createBefore(packet.ptr()));
334 }
335 
336 template <class PacketType>
337 prefix_ senf::ConcretePacket<PacketType>
338 senf::ConcretePacket<PacketType>::createBefore(Packet const & packet, senf::NoInit_t,
339  size_type space, size_type tailSpace)
340 {
341  return ConcretePacket(interpreter::createBefore(packet.ptr(), senf::noinit, space, tailSpace));
342 }
343 
344 template <class PacketType>
345 prefix_ senf::ConcretePacket<PacketType>
346 senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet)
347 {
348  return ConcretePacket(interpreter::createInsertBefore(packet.ptr()));
349 }
350 
351 template <class PacketType>
352 prefix_ senf::ConcretePacket<PacketType>
353 senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet, senf::NoInit_t)
354 {
355  return ConcretePacket(interpreter::createInsertBefore(packet.ptr(), senf::noinit));
356 }
357 
358 // Create a clone of the current packet
359 
360 template <class PacketType>
361 prefix_ senf::ConcretePacket<PacketType>
362 senf::ConcretePacket<PacketType>::clone()
363  const
364 {
365  return ConcretePacket(ptr()->clone());
366 }
367 
368 // Field access
369 
370 template <class PacketType>
371 prefix_ typename senf::ConcretePacket<PacketType>::Parser
372 senf::ConcretePacket<PacketType>::parser()
373  const
374 {
375  return ptr()->fields();
376 }
377 
378 template <class PacketType>
379 prefix_ typename senf::ConcretePacket<PacketType>::ParserProxy
380 senf::ConcretePacket<PacketType>::operator->()
381  const
382 {
383  return ParserProxy(parser());
384 }
385 
386 template <class PacketType>
387 prefix_ senf::Packet senf::ConcretePacket<PacketType>::next(NoThrow_t)
388  const
389 {
390  PacketInterpreterBase::ptr p (Packet::ptr()->next());
391  if (p) return Packet(p);
392  PacketInterpreterBase::optional_range r (type::nextPacketRange(*this));
393  return (r && ! r->empty()) ? Packet(getNext(r)) : Packet();
394 }
395 
396 // private members
397 
398 template <class PacketType>
399 prefix_ senf::ConcretePacket<PacketType>::ConcretePacket(typename interpreter::ptr const & packet_)
400  : Packet(packet_)
401 {}
402 
403 template <class PacketType>
404 prefix_ typename senf::ConcretePacket<PacketType>::interpreter * senf::ConcretePacket<PacketType>::ptr()
405  const
406 {
407  return static_cast< PacketInterpreter<PacketType> *>( Packet::ptr().get());
408 }
409 
410 //-/////////////////////////////////////////////////////////////////////////////////////////////////
411 #undef prefix_
412 
413 
414 // Local Variables:
415 // mode: c++
416 // fill-column: 100
417 // c-file-style: "senf"
418 // indent-tabs-mode: nil
419 // ispell-local-dictionary: "american"
420 // compile-command: "scons -u test"
421 // comment-column: 40
422 // End: