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
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
15 \brief Packet inline template implementation */
17 //#include "Packet.ih"
20 #include <senf/Utils/Exception.hh>
21 #include <senf/Utils/senflikely.hh>
23 #define prefix_ inline
24 //-/////////////////////////////////////////////////////////////////////////////////////////////////
26 //-/////////////////////////////////////////////////////////////////////////////////////////////////
29 // conversion constructors
31 template <class PacketType>
32 prefix_ senf::Packet::Packet(ConcretePacket<PacketType> const & packet)
33 : packet_(packet.ptr())
40 // interpreter chain access
42 template <class OtherPacket>
43 prefix_ OtherPacket senf::Packet::parseNextAs()
46 return OtherPacket(ptr()->parseNextAs<typename OtherPacket::type>());
49 template <class OtherPacket>
50 prefix_ bool senf::Packet::is()
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>();
59 template <class OtherPacket>
60 prefix_ OtherPacket const & senf::Packet::as()
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
71 return static_cast<OtherPacket const &>(*this);
74 template <class OtherPacket>
75 prefix_ OtherPacket & senf::Packet::as()
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
85 return static_cast<OtherPacket &>(*this);
88 template <class OtherPacket>
89 prefix_ OtherPacket const & senf::Packet::as(NoThrow_t)
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
96 return static_cast<OtherPacket const &>(*this);
99 template <class OtherPacket>
100 prefix_ OtherPacket & senf::Packet::as(NoThrow_t)
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
106 return static_cast<OtherPacket &>(*this);
109 template <class OtherPacket>
110 prefix_ OtherPacket senf::Packet::next()
113 return next().as<OtherPacket>();
116 template <class OtherPacket>
117 prefix_ OtherPacket senf::Packet::next(NoThrow_t)
120 Packet p (next(nothrow));
121 return SENF_LIKELY(p && p.is<OtherPacket>()) ?
122 OtherPacket(p.ptr()->as<typename OtherPacket::type>()) : OtherPacket();
125 template <class OtherPacket>
126 prefix_ OtherPacket senf::Packet::find()
129 OtherPacket p (find<OtherPacket>(nothrow));
130 if (!p) throw InvalidPacketChainException();
134 template <class OtherPacket>
135 prefix_ OtherPacket senf::Packet::prev()
138 return prev().as<OtherPacket>();
141 template <class OtherPacket>
142 prefix_ OtherPacket senf::Packet::prev(NoThrow_t)
145 Packet p (prev(nothrow));
146 return p && p.is<OtherPacket>() ?
147 OtherPacket(p.ptr()->as<typename OtherPacket::type>()) : OtherPacket();
150 template <class OtherPacket>
151 prefix_ OtherPacket senf::Packet::rfind()
154 OtherPacket p (rfind<OtherPacket>(nothrow));
155 if (!p) throw InvalidPacketChainException();
159 template <class OtherPacket>
160 prefix_ OtherPacket senf::Packet::last()
163 return last().as<OtherPacket>();
166 template <class OtherPacket>
167 prefix_ OtherPacket senf::Packet::first()
170 return first().as<OtherPacket>();
173 template <class Other>
174 prefix_ void senf::Packet::finalizeTo()
176 Packet p (find<Other>(nothrow));
177 ptr()->finalizeTo(p ? p.ptr() : last().ptr());
180 template <class Annotation>
181 prefix_ Annotation & senf::Packet::annotation()
183 return ptr()->annotation<Annotation>();
186 template <class Annotation>
187 prefix_ Annotation const & senf::Packet::annotation()
190 return ptr()->annotation<Annotation>();
193 template <class OtherPacket>
194 prefix_ OtherPacket senf::Packet::replaceAs(difference_type offset, difference_type tailOffset)
196 OtherPacket res (ptr()->replaceAs<typename OtherPacket::type>(offset, tailOffset));
201 template <class PacketType, class Parser>
202 prefix_ Parser senf::operator<<(Parser target, ConcretePacket<PacketType> const & packet)
204 target << packet.parser();
208 //-/////////////////////////////////////////////////////////////////////////////////////////////////
209 // senf::ConcretePacket<PacketType>
211 // structors and default members
213 template <class PacketType>
214 prefix_ senf::ConcretePacket<PacketType>::ConcretePacket()
218 template <class PacketType>
219 prefix_ typename senf::ConcretePacket<PacketType>::factory_t
220 senf::ConcretePacket<PacketType>::factory()
222 return interpreter::factory();
225 // Create completely new packet
227 template <class PacketType>
228 prefix_ senf::ConcretePacket<PacketType>
229 senf::ConcretePacket<PacketType>::create()
231 return ConcretePacket(interpreter::create());
234 template <class PacketType>
235 prefix_ senf::ConcretePacket<PacketType>
236 senf::ConcretePacket<PacketType>::create(senf::NoInit_t)
238 return ConcretePacket(interpreter::create(senf::noinit));
241 template <class PacketType>
242 prefix_ senf::ConcretePacket<PacketType>
243 senf::ConcretePacket<PacketType>::create(size_type size)
245 return ConcretePacket(interpreter::create(size));
248 template <class PacketType>
249 prefix_ senf::ConcretePacket<PacketType>
250 senf::ConcretePacket<PacketType>::create(size_type size, senf::NoInit_t)
252 return ConcretePacket(interpreter::create(size,senf::noinit));
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 *)
263 return ConcretePacket(interpreter::create(range));
268 template <class PacketType>
269 prefix_ senf::ConcretePacket<PacketType>
270 senf::ConcretePacket<PacketType>::create(byte * data, size_type size, size_type chunkSize,
273 return ConcretePacket(interpreter::create(data, size, chunkSize, offset));
276 // Create packet as new packet after a given packet
278 template <class PacketType>
279 prefix_ senf::ConcretePacket<PacketType>
280 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet)
282 return ConcretePacket(interpreter::createAfter(packet.ptr()));
285 template <class PacketType>
286 prefix_ senf::ConcretePacket<PacketType>
287 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, senf::NoInit_t)
289 return ConcretePacket(interpreter::createAfter(packet.ptr(),senf::noinit));
292 template <class PacketType>
293 prefix_ senf::ConcretePacket<PacketType>
294 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size)
296 return ConcretePacket(interpreter::createAfter(packet.ptr(), size));
299 template <class PacketType>
300 prefix_ senf::ConcretePacket<PacketType>
301 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size,
304 return ConcretePacket(interpreter::createAfter(packet.ptr(), size, senf::noinit));
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 *)
315 return ConcretePacket(interpreter::createAfter(packet.ptr(), range));
320 // Create packet as new packet (header) before a given packet
322 template <class PacketType>
323 prefix_ senf::ConcretePacket<PacketType>
324 senf::ConcretePacket<PacketType>::createBefore(Packet const & packet)
326 return ConcretePacket(interpreter::createBefore(packet.ptr()));
329 template <class PacketType>
330 prefix_ senf::ConcretePacket<PacketType>
331 senf::ConcretePacket<PacketType>::createBeforeNoZero(Packet const & packet)
333 return ConcretePacket(interpreter::createBefore(packet.ptr()));
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)
341 return ConcretePacket(interpreter::createBefore(packet.ptr(), senf::noinit, space, tailSpace));
344 template <class PacketType>
345 prefix_ senf::ConcretePacket<PacketType>
346 senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet)
348 return ConcretePacket(interpreter::createInsertBefore(packet.ptr()));
351 template <class PacketType>
352 prefix_ senf::ConcretePacket<PacketType>
353 senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet, senf::NoInit_t)
355 return ConcretePacket(interpreter::createInsertBefore(packet.ptr(), senf::noinit));
358 // Create a clone of the current packet
360 template <class PacketType>
361 prefix_ senf::ConcretePacket<PacketType>
362 senf::ConcretePacket<PacketType>::clone()
365 return ConcretePacket(ptr()->clone());
370 template <class PacketType>
371 prefix_ typename senf::ConcretePacket<PacketType>::Parser
372 senf::ConcretePacket<PacketType>::parser()
375 return ptr()->fields();
378 template <class PacketType>
379 prefix_ typename senf::ConcretePacket<PacketType>::ParserProxy
380 senf::ConcretePacket<PacketType>::operator->()
383 return ParserProxy(parser());
386 template <class PacketType>
387 prefix_ senf::Packet senf::ConcretePacket<PacketType>::next(NoThrow_t)
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();
398 template <class PacketType>
399 prefix_ senf::ConcretePacket<PacketType>::ConcretePacket(typename interpreter::ptr const & packet_)
403 template <class PacketType>
404 prefix_ typename senf::ConcretePacket<PacketType>::interpreter * senf::ConcretePacket<PacketType>::ptr()
407 return static_cast< PacketInterpreter<PacketType> *>( Packet::ptr().get());
410 //-/////////////////////////////////////////////////////////////////////////////////////////////////
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