2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
22 \brief PacketInterpreter inline template implementation */
24 //#include "PacketInterpreter.ih"
28 #define prefix_ inline
29 ///////////////////////////////cti.p///////////////////////////////////////
31 ///////////////////////////////////////////////////////////////////////////
32 // senf::PacketInterpreterBase
34 // Interpreter chain access
37 prefix_ bool senf::PacketInterpreterBase::is()
39 return dynamic_cast< PacketInterpreter<Type>* >(this);
43 prefix_ typename senf::PacketInterpreter<Type>::ptr senf::PacketInterpreterBase::as()
45 return typename PacketInterpreter<Type>::ptr(
46 static_cast< PacketInterpreter<Type>* >(this));
49 ///////////////////////////////////////////////////////////////////////////
50 // senf::PacketInterpreter<PacketType>
52 template <class PacketType>
53 prefix_ senf::PacketInterpreter<PacketType>::~PacketInterpreter()
55 parser_p()->~parser();
58 template <class PacketType>
59 prefix_ typename senf::PacketInterpreter<PacketType>::factory_t
60 senf::PacketInterpreter<PacketType>::factory()
65 // Create completely new packet
67 template <class PacketType>
68 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
69 senf::PacketInterpreter<PacketType>::create()
71 return create(initSize());
74 template <class PacketType>
75 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
76 senf::PacketInterpreter<PacketType>::create(NoInit_t)
78 return create(0,noinit);
81 template <class PacketType>
82 template <class ForwardReadableRange>
83 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
84 senf::PacketInterpreter<PacketType>::create(ForwardReadableRange const & range)
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));
91 // Create packet as new packet after a given packet
93 template <class PacketType>
94 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
95 senf::PacketInterpreter<PacketType>::createAfter(PacketInterpreterBase::ptr packet)
97 return createAfter(packet, initSize());
100 template <class PacketType>
101 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
102 senf::PacketInterpreter<PacketType>::createAfter(PacketInterpreterBase::ptr packet, NoInit_t)
104 return createAfter(packet, 0, noinit);
107 // Create clone of current packet
109 template <class PacketType>
110 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
111 senf::PacketInterpreter<PacketType>::clone()
113 return boost::static_pointer_cast<typename ptr::element_type>(PacketInterpreterBase::clone());
116 // Packet field access
118 template <class PacketType>
119 prefix_ typename senf::PacketInterpreter<PacketType>::parser
120 senf::PacketInterpreter<PacketType>::fields()
122 return parser(&data());
125 template <class PacketType>
126 prefix_ typename senf::PacketInterpreter<PacketType>::parser *
127 senf::PacketInterpreter<PacketType>::fields_p()
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).
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.
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).
146 parser_p()->~parser();
147 new (parser_p()) parser (data().begin(),&data());
151 ////////////////////////////////////////
156 template <class PacketType>
157 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
158 senf::PacketInterpreter<PacketType>::create(detail::PacketImpl * impl, iterator b, iterator e,
161 return ptr(new PacketInterpreter(impl,b,e,Append));
164 template <class PacketType>
165 prefix_ typename senf::PacketInterpreter<PacketType>::ptr
166 senf::PacketInterpreter<PacketType>::create(detail::PacketImpl * impl, iterator b, iterator e,
169 return ptr(new PacketInterpreter(impl,b,e,Prepend));
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)
177 new (parser_p()) parser (data().begin(),&data());
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)
185 new (parser_p()) parser (data().begin(),&data());
190 template <class PacketType>
191 prefix_ typename senf::PacketInterpreter<PacketType>::size_type
192 senf::PacketInterpreter<PacketType>::initSize()
194 return type::initSize();
197 template <class PacketType>
198 prefix_ typename senf::PacketInterpreter<PacketType>::size_type
199 senf::PacketInterpreter<PacketType>::initHeadSize()
201 size_type sz (type::initHeadSize());
202 return sz == size_type(-1) ? initSize() : sz ;
205 template <class PacketType>
206 prefix_ void senf::PacketInterpreter<PacketType>::init()
208 return type::init(ConcretePacket<PacketType>(ptr(this)));
211 template <class PacketType>
212 prefix_ typename senf::PacketInterpreter<PacketType>::parser *
213 senf::PacketInterpreter<PacketType>::parser_p()
215 return reinterpret_cast<parser *>(&parserStorage_);
218 ///////////////////////////////cti.e///////////////////////////////////////
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