Reapply changes missed during the previous merge (duh ...)
[senf.git] / Packets / PacketInterpreter.cti
1 // Copyright (C) 2007 
2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 //     Stefan Bund <g0dil@berlios.de>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 /** \file
22     \brief PacketInterpreter inline template implementation */
23
24 //#include "PacketInterpreter.ih"
25
26 // Custom includes
27
28 #define prefix_ inline
29 ///////////////////////////////cti.p///////////////////////////////////////
30
31 ///////////////////////////////////////////////////////////////////////////
32 // senf::PacketInterpreterBase
33
34 // Interpreter chain access
35
36 template <class Type>
37 prefix_ bool senf::PacketInterpreterBase::is()
38 {
39     return dynamic_cast< PacketInterpreter<Type>* >(this);
40 }
41
42 template <class Type>
43 prefix_ typename senf::PacketInterpreter<Type>::ptr senf::PacketInterpreterBase::as()
44 {
45     return typename PacketInterpreter<Type>::ptr(
46         static_cast< PacketInterpreter<Type>* >(this));
47 }
48
49 ///////////////////////////////////////////////////////////////////////////
50 // senf::PacketInterpreter<PacketType>
51
52 template <class PacketType>
53 prefix_ senf::PacketInterpreter<PacketType>::~PacketInterpreter()
54 {
55     parser_p()->~parser();
56 }
57
58 template <class PacketType>
59 prefix_ typename senf::PacketInterpreter<PacketType>::factory_t
60 senf::PacketInterpreter<PacketType>::factory()
61 {
62     return & factory_;
63 }
64
65 // Create completely new packet
66
67 template <class PacketType>
68 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
69 senf::PacketInterpreter<PacketType>::create()
70 {
71     return create(initSize());
72 }
73
74 template <class PacketType>
75 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
76 senf::PacketInterpreter<PacketType>::create(NoInit_t)
77 {
78     return create(0,noinit);
79 }
80
81 template <class PacketType>
82 template <class ForwardReadableRange>
83 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
84 senf::PacketInterpreter<PacketType>::create(ForwardReadableRange const & range)
85 {
86     detail::PacketImpl::Guard p (new detail::PacketImpl(boost::begin(range),boost::end(range)));
87     ptr pi (create(p.p,p.p->begin(),p.p->end(),Append));
88     return pi;
89 }
90
91 // Create packet as new packet after a given packet
92
93 template <class PacketType>
94 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
95 senf::PacketInterpreter<PacketType>::createAfter(PacketInterpreterBase::ptr packet)
96 {
97     return createAfter(packet, initSize());
98 }
99
100 template <class PacketType>
101 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
102 senf::PacketInterpreter<PacketType>::createAfter(PacketInterpreterBase::ptr packet, NoInit_t)
103 {
104     return createAfter(packet, 0, noinit);
105 }
106
107 // Create clone of current packet
108
109 template <class PacketType>
110 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
111 senf::PacketInterpreter<PacketType>::clone()
112 {
113     return boost::static_pointer_cast<typename ptr::element_type>(PacketInterpreterBase::clone());
114 }
115
116 // Packet field access
117
118 template <class PacketType>
119 prefix_ typename senf::PacketInterpreter<PacketType>::parser
120 senf::PacketInterpreter<PacketType>::fields()
121 {
122     return parser(&data());
123 }
124
125 template <class PacketType>
126 prefix_ typename senf::PacketInterpreter<PacketType>::parser *
127 senf::PacketInterpreter<PacketType>::fields_p()
128 {
129     // This is somewhat awkward. We want to allow the user to access the packet's field using the
130     // 'operator->' member of the packet class (the handle). Now, 'operator->' *must* return a
131     // pointer to a non-dynamically allocated object. So where should it point to? We need to return
132     // a pointer to a parser instance, but parser instances are designed to be transient (they are
133     // invalidated whenever a packet's size is changed).
134
135     // What we do is the following: parserStorage_ is an (initialy uninitialized) storage area
136     // within the interpreter with enough space (and correct alignment) to take hold of a parser
137     // instance. In the constructor we use placement new to construct a parser in this area which we
138     // explicit dispose of in the destructor. Now, whenever the fields_p() member is called, we
139     // destroy the parser object and recreate it. 
140
141     // This does introduce one additional problem: It is not safe for multiple threads to
142     // concurrently read from the same packet. On the other hand, the packet classes are not
143     // syncronized in any way and are not safe to use from multiple threads anyways (e.g. the lazy
144     // packet chain makes some read-only operations change the packet which is not thread safe).
145
146     parser_p()->~parser();
147     new (parser_p()) parser (data().begin(),&data());
148     return parser_p();
149 }
150
151 ////////////////////////////////////////
152 // private members
153
154 // Private structors
155
156 template <class PacketType>
157 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
158 senf::PacketInterpreter<PacketType>::create(detail::PacketImpl * impl, iterator b, iterator e,
159                                             Append_t)
160 {
161     return ptr(new PacketInterpreter(impl,b,e,Append));
162 }
163
164 template <class PacketType>
165 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
166 senf::PacketInterpreter<PacketType>::create(detail::PacketImpl * impl, iterator b, iterator e,
167                                             Prepend_t)
168 {
169     return ptr(new PacketInterpreter(impl,b,e,Prepend));
170 }
171
172 template <class PacketType>
173 prefix_ senf::PacketInterpreter<PacketType>::PacketInterpreter(detail::PacketImpl * impl,
174                                                                iterator b, iterator e, Append_t)
175     : PacketInterpreterBase(impl,b,e,Append)
176 {
177     new (parser_p()) parser (data().begin(),&data());
178 }
179
180 template <class PacketType>
181 prefix_ senf::PacketInterpreter<PacketType>::PacketInterpreter(detail::PacketImpl * impl,
182                                                                iterator b, iterator e, Prepend_t)
183     : PacketInterpreterBase(impl,b,e,Prepend)
184 {
185     new (parser_p()) parser (data().begin(),&data());
186 }
187
188 // PacketType access
189
190 template <class PacketType>
191 prefix_ typename senf::PacketInterpreter<PacketType>::size_type
192 senf::PacketInterpreter<PacketType>::initSize()
193 {
194     return type::initSize();
195 }
196
197 template <class PacketType>
198 prefix_ typename senf::PacketInterpreter<PacketType>::size_type
199 senf::PacketInterpreter<PacketType>::initHeadSize()
200 {
201     size_type sz (type::initHeadSize());
202     return  sz == size_type(-1) ? initSize() : sz ;
203 }
204
205 template <class PacketType>
206 prefix_ void senf::PacketInterpreter<PacketType>::init()
207 {
208     return type::init(ConcretePacket<PacketType>(ptr(this)));
209 }
210
211 template <class PacketType>
212 prefix_ typename senf::PacketInterpreter<PacketType>::parser *
213 senf::PacketInterpreter<PacketType>::parser_p()
214 {
215     return reinterpret_cast<parser *>(&parserStorage_);
216 }
217
218 ///////////////////////////////cti.e///////////////////////////////////////
219 #undef prefix_
220
221 \f
222 // Local Variables:
223 // mode: c++
224 // fill-column: 100
225 // c-file-style: "senf"
226 // indent-tabs-mode: nil
227 // ispell-local-dictionary: "american"
228 // compile-command: "scons -u test"
229 // comment-column: 40
230 // End: