Packet: optimized Packet.is<> member by removing dynamic_cast
[senf.git] / senf / Packets / Packet.cti
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Packet inline template implementation */
30
31 //#include "Packet.ih"
32
33 // Custom includes
34 #include <senf/Utils/Exception.hh>
35
36 #define prefix_ inline
37 //-/////////////////////////////////////////////////////////////////////////////////////////////////
38
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40 // senf::Packet
41
42 // conversion constructors
43
44 template <class PacketType>
45 prefix_ senf::Packet::Packet(ConcretePacket<PacketType> const & packet)
46     : packet_(packet.ptr())
47 {}
48
49 // interpreter chain access
50
51 template <class OtherPacket>
52 prefix_ OtherPacket senf::Packet::parseNextAs()
53     const
54 {
55     return OtherPacket(ptr()->parseNextAs<typename OtherPacket::type>());
56 }
57
58 template <class OtherPacket>
59 prefix_ bool senf::Packet::is()
60     const
61 {
62     // ensure that the template class is included in the corresponding object file when linking:
63     { static typename PacketInterpreter<typename OtherPacket::type>::factory_t _ (
64             PacketInterpreter<typename OtherPacket::type>::factory()); (void) _;}
65     return valid() && typeId() == typeIdValue<OtherPacket>();
66 }
67
68 template <class OtherPacket>
69 prefix_ OtherPacket senf::Packet::as()
70     const
71 {
72     if (!is<OtherPacket>())
73         throw WrapException<std::bad_cast>(std::bad_cast())
74             << ": called packet::as() with wrong PacketType: "
75             << (valid() ? typeId().prettyName() : "invalid packet")
76             << " != " << prettyName(typeid(OtherPacket));
77     return OtherPacket(ptr()->as<typename OtherPacket::type>());
78 }
79
80 template <class OtherPacket>
81 prefix_ OtherPacket senf::Packet::as(NoThrow_t)
82     const
83 {
84     SENF_ASSERT( is<OtherPacket>(), "Bad cast, called packet::as(nothrow) with wrong PacketType");
85     return OtherPacket(ptr()->as<typename OtherPacket::type>());
86 }
87
88 template <class OtherPacket>
89 prefix_ OtherPacket senf::Packet::next()
90     const
91 {
92     return next().as<OtherPacket>();
93 }
94
95 template <class OtherPacket>
96 prefix_ OtherPacket senf::Packet::next(NoThrow_t)
97     const
98 {
99     Packet p (next(nothrow));
100     return p && p.is<OtherPacket>() ?
101             OtherPacket(p.ptr()->as<typename OtherPacket::type>()) : OtherPacket();
102 }
103
104 template <class OtherPacket>
105 prefix_ OtherPacket senf::Packet::find()
106     const
107 {
108     OtherPacket p (find<OtherPacket>(nothrow));
109     if (!p) throw InvalidPacketChainException();
110     return p;
111 }
112
113 template <class OtherPacket>
114 prefix_ OtherPacket senf::Packet::prev()
115     const
116 {
117     return prev().as<OtherPacket>();
118 }
119
120 template <class OtherPacket>
121 prefix_ OtherPacket senf::Packet::prev(NoThrow_t)
122     const
123 {
124     Packet p (prev(nothrow));
125     return p && p.is<OtherPacket>() ?
126             OtherPacket(p.ptr()->as<typename OtherPacket::type>()) : OtherPacket();
127 }
128
129 template <class OtherPacket>
130 prefix_ OtherPacket senf::Packet::rfind()
131     const
132 {
133     OtherPacket p (rfind<OtherPacket>(nothrow));
134     if (!p) throw InvalidPacketChainException();
135     return p;
136 }
137
138 template <class OtherPacket>
139 prefix_ OtherPacket senf::Packet::last()
140     const
141 {
142     return last().as<OtherPacket>();
143 }
144
145 template <class OtherPacket>
146 prefix_ OtherPacket senf::Packet::first()
147     const
148 {
149     return first().as<OtherPacket>();
150 }
151
152 template <class Other>
153 prefix_ void senf::Packet::finalizeTo()
154 {
155     Packet p (find<Other>(nothrow));
156     ptr()->finalizeTo(p ? p.ptr() : last().ptr());
157 }
158
159 template <class Annotation>
160 prefix_ Annotation & senf::Packet::annotation()
161 {
162     return ptr()->annotation<Annotation>();
163 }
164
165 template <class Annotation>
166 prefix_ Annotation const & senf::Packet::annotation()
167     const
168 {
169     return ptr()->annotation<Annotation>();
170 }
171
172 //-/////////////////////////////////////////////////////////////////////////////////////////////////
173 // senf::ConcretePacket<PacketType>
174
175 // structors and default members
176
177 template <class PacketType>
178 prefix_ senf::ConcretePacket<PacketType>::ConcretePacket()
179 {}
180
181 template <class PacketType>
182 prefix_ typename senf::ConcretePacket<PacketType>::factory_t
183 senf::ConcretePacket<PacketType>::factory()
184 {
185     return interpreter::factory();
186 }
187
188 // Create completely new packet
189
190 template <class PacketType>
191 prefix_ senf::ConcretePacket<PacketType>
192 senf::ConcretePacket<PacketType>::create()
193 {
194     return ConcretePacket(interpreter::create());
195 }
196
197 template <class PacketType>
198 prefix_ senf::ConcretePacket<PacketType>
199 senf::ConcretePacket<PacketType>::create(senf::NoInit_t)
200 {
201     return ConcretePacket(interpreter::create(senf::noinit));
202 }
203
204 template <class PacketType>
205 prefix_ senf::ConcretePacket<PacketType>
206 senf::ConcretePacket<PacketType>::create(size_type size)
207 {
208     return ConcretePacket(interpreter::create(size));
209 }
210
211 template <class PacketType>
212 prefix_ senf::ConcretePacket<PacketType>
213 senf::ConcretePacket<PacketType>::create(size_type size, senf::NoInit_t)
214 {
215     return ConcretePacket(interpreter::create(size,senf::noinit));
216 }
217
218 #ifndef DOXYGEN
219
220 template <class PacketType>
221 template <class ForwardReadableRange>
222 prefix_ senf::ConcretePacket<PacketType> senf::ConcretePacket<PacketType>::
223 create(ForwardReadableRange const & range,
224        typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type *)
225 {
226     return ConcretePacket(interpreter::create(range));
227 }
228
229 #endif
230
231 // Create packet as new packet after a given packet
232
233 template <class PacketType>
234 prefix_ senf::ConcretePacket<PacketType>
235 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet)
236 {
237     return ConcretePacket(interpreter::createAfter(packet.ptr()));
238 }
239
240 template <class PacketType>
241 prefix_ senf::ConcretePacket<PacketType>
242 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, senf::NoInit_t)
243 {
244     return ConcretePacket(interpreter::createAfter(packet.ptr(),senf::noinit));
245 }
246
247 template <class PacketType>
248 prefix_ senf::ConcretePacket<PacketType>
249 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size)
250 {
251     return ConcretePacket(interpreter::createAfter(packet.ptr(), size));
252 }
253
254 template <class PacketType>
255 prefix_ senf::ConcretePacket<PacketType>
256 senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size,
257                                               senf::NoInit_t)
258 {
259     return ConcretePacket(interpreter::createAfter(packet.ptr(), size, senf::noinit));
260 }
261
262 #ifndef DOXYGEN
263
264 template <class PacketType>
265 template <class ForwardReadableRange>
266 prefix_ senf::ConcretePacket<PacketType> senf::ConcretePacket<PacketType>::
267 createAfter(Packet const & packet, ForwardReadableRange const & range,
268             typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type *)
269 {
270     return ConcretePacket(interpreter::createAfter(packet.ptr(), range));
271 }
272
273 #endif
274
275 // Create packet as new packet (header) before a given packet
276
277 template <class PacketType>
278 prefix_ senf::ConcretePacket<PacketType>
279 senf::ConcretePacket<PacketType>::createBefore(Packet const & packet)
280 {
281     return ConcretePacket(interpreter::createBefore(packet.ptr()));
282 }
283
284 template <class PacketType>
285 prefix_ senf::ConcretePacket<PacketType>
286 senf::ConcretePacket<PacketType>::createBefore(Packet const & packet, senf::NoInit_t)
287 {
288     return ConcretePacket(interpreter::createBefore(packet.ptr(), senf::noinit));
289 }
290
291 template <class PacketType>
292 prefix_ senf::ConcretePacket<PacketType>
293 senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet)
294 {
295     return ConcretePacket(interpreter::createInsertBefore(packet.ptr()));
296 }
297
298 template <class PacketType>
299 prefix_ senf::ConcretePacket<PacketType>
300 senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet, senf::NoInit_t)
301 {
302     return ConcretePacket(interpreter::createInsertBefore(packet.ptr(), senf::noinit));
303 }
304
305 // Create a clone of the current packet
306
307 template <class PacketType>
308 prefix_ senf::ConcretePacket<PacketType>
309 senf::ConcretePacket<PacketType>::clone()
310     const
311 {
312     return ConcretePacket(ptr()->clone());
313 }
314
315 // Field access
316
317 template <class PacketType>
318 prefix_ typename senf::ConcretePacket<PacketType>::Parser
319 senf::ConcretePacket<PacketType>::parser()
320     const
321 {
322     return ptr()->fields();
323 }
324
325 template <class PacketType>
326 prefix_ typename senf::ConcretePacket<PacketType>::ParserProxy
327 senf::ConcretePacket<PacketType>::operator->()
328     const
329 {
330     return ParserProxy(parser());
331 }
332
333 template <class PacketType>
334 prefix_ senf::Packet senf::ConcretePacket<PacketType>::next(NoThrow_t)
335     const
336 {
337     PacketInterpreterBase::ptr p (Packet::ptr()->next());
338     if (p) return Packet(p);
339     PacketInterpreterBase::optional_range r (type::nextPacketRange(*this));
340     return (r && ! r->empty()) ? getNext(r) : Packet();
341 }
342
343 // private members
344
345 template <class PacketType>
346 prefix_ senf::ConcretePacket<PacketType>::ConcretePacket(typename interpreter::ptr const & packet_)
347     : Packet(packet_)
348 {}
349
350 template <class PacketType>
351 prefix_ typename senf::ConcretePacket<PacketType>::interpreter * senf::ConcretePacket<PacketType>::ptr()
352     const
353 {
354     return static_cast< PacketInterpreter<PacketType> *>( Packet::ptr().get());
355 }
356
357 //-/////////////////////////////////////////////////////////////////////////////////////////////////
358 #undef prefix_
359
360 \f
361 // Local Variables:
362 // mode: c++
363 // fill-column: 100
364 // c-file-style: "senf"
365 // indent-tabs-mode: nil
366 // ispell-local-dictionary: "american"
367 // compile-command: "scons -u test"
368 // comment-column: 40
369 // End: