Fixed whitespace in all files (no tabs)
[senf.git] / Packets / Packet.cc
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 // Definition of non-inline non-template functions
24
25 #include "Packet.hh"
26 #include "Packet.ih"
27
28 // Custom includes
29 #include <boost/utility.hpp> // for next/prior
30
31 #define prefix_
32 ///////////////////////////////cc.p////////////////////////////////////////
33
34 ///////////////////////////////////////////////////////////////////////////
35 // REFERENCE COUNTING
36 ///////////////////////////////////////////////////////////////////////////
37
38 // We manage TWO reference counts:
39 //
40 // - The first reference counts lives wihin PacketImpl. It counts the
41 //   number of references to the PacketImpl instance
42 //
43 // - The second reference count lives with the Packet interpreters. It
44 //   counts the number of external references to the Packet facades.
45 //
46 // The PacketImpl refcount is always the sum of all it's Packet
47 // interpreter member refcounts.
48 //
49 // The Packet facades are referenced from two sides:
50 //
51 // - From the user. These references are counted in the Packet
52 //   refcount.
53 //
54 // - From the list of interpreters. These references are *not*
55 //   counted.
56 //
57 // The Packet facades have an impl_ member. This is set to non-0 only,
58 // as long as the Packet is a list member. The Packet may be deleted,
59 // when impl_ == 0 and refcount_ == 0.
60
61 // class ListPacketDeleter
62
63 // This is the custom deleter used for the pointers in the
64 // interpreters list. This deleter is only called, when the Packet is
65 // removed from the interpreters list.
66 prefix_ void senf::impl::ListPacketDeleter::operator()(Packet * p)
67 {
68     PacketImpl * impl = PacketImpl::impl(p);
69     if (impl->releaseInterpreter(p))
70         delete impl;
71 }
72
73 // struct PacketImpl
74
75 prefix_ senf::Packet::interpreter_list::iterator
76 senf::impl::PacketImpl::appendInterpreter(Packet * p)
77 {
78     BOOST_ASSERT( p->impl_ == 0 );
79
80     this->refcount_ += p->refcount_;
81     SATCOM_PKF_REFC_MSG("] PacketImpl::appendInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
82     p->impl_ = this;
83     this->interpreters_.push_back(
84         boost::shared_ptr<Packet>(p, impl::ListPacketDeleter()));
85
86     p->self_ = boost::prior(this->interpreters_.end());
87     return p->self_;
88 }
89
90 prefix_ senf::Packet::interpreter_list::iterator
91 senf::impl::PacketImpl::prependInterpreter(Packet * p)
92 {
93     BOOST_ASSERT( p->impl_ == 0 );
94
95     this->refcount_ += p->refcount_;
96     SATCOM_PKF_REFC_MSG("] PacketImpl::prependInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
97     p->impl_ = this;
98     this->interpreters_.push_front(
99         boost::shared_ptr<Packet>(p, impl::ListPacketDeleter()));
100
101     p->self_ = this->interpreters_.begin();
102     return p->self_;
103 }
104
105 // Called, whenever a Packet is removed from the list by the
106 // ListPacketDeleter;
107 prefix_ bool senf::impl::PacketImpl::releaseInterpreter(Packet * p)
108 {
109     // We have to be extra careful here: This method might be called
110     // AFTER the PacketImpl instance has already been destructed while
111     // destructing the interpreters list !!
112     // If p->refcount_ is > 0 however we know, that this->refcount_
113     // must also be > 0 ...
114     // So we have to make sure never to access this if p->refcount_==0
115     BOOST_ASSERT( p->impl_ == this );
116     bool rv (false);
117     if (p->refcount_ > 0) {
118         this->refcount_ -= p->refcount_;
119         rv = !this->refcount_;
120         SATCOM_PKF_REFC_MSG("] PacketImpl::releaseInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
121     }
122     if (p->unlink())
123         delete p;
124     return rv;
125 }
126
127 namespace {
128     bool whenceCmp(unsigned a, unsigned b, bool end, senf::Packet::Whence whence)
129     {
130         using senf::Packet;
131         return ((whence == Packet::OUTSIDE && ! end)
132                 || whence == Packet::BEFORE
133                 || (whence == Packet::INSIDE && end)) ? a>=b : a>b;
134     }
135 }
136
137 prefix_ void
138 senf::impl::PacketImpl::updateIterators(Packet::size_type index,
139                                                Packet::difference_type n,
140                                                Packet::interpreter_list::iterator self,
141                                                Packet::Whence whence)
142 {
143     Packet::interpreter_list::iterator i (interpreters_.begin());
144     Packet::interpreter_list::iterator const e (interpreters_.end());
145     Packet::Whence w (whence == Packet::AUTO ? Packet::INSIDE : whence);
146     for (;i!=e;++i) {
147         if (whenceCmp((*i)->end_,index,true,w))
148             if (n<0 && (*i)->end_ < index-n)
149                 (*i)->end_ = index;
150             else
151                 (*i)->end_ += n;
152         if (whenceCmp((*i)->begin_,index,false,w))
153             if (n<0 && (*i)->begin_ < index-n)
154                 (*i)->begin_ = index;
155             else
156                 (*i)->begin_ += n;
157         if (i == self && whence == Packet::AUTO) w = Packet::OUTSIDE;
158         BOOST_ASSERT( (*i)->end_ >= (*i)->begin_ );
159     }
160 }
161
162 prefix_ void senf::impl::PacketImpl::packet_add_ref(Packet const * p)
163 {
164     p->add_ref();
165     if (p->impl_)
166         p->impl_->add_ref();
167 }
168
169 prefix_ void senf::impl::PacketImpl::packet_release(Packet * p)
170 {
171     bool del (p->release());
172     if (p->impl_ && p->impl_->release())
173         // In this case, del is certainly false here. p might
174         // however get deleted now.
175         delete p->impl_;
176     if (del)
177         delete p;
178 }
179
180 ///////////////////////////////////////////////////////////////////////////
181 // class Packet
182
183 prefix_ senf::Packet::ptr senf::Packet::next()
184     const
185 {
186     interpreter_list::iterator n = boost::next(this->self_);
187     if (n == this->impl_->interpreters_.end()) {
188         if (this->parsed_)
189             return ptr(0);
190         /* \fixme v_nextInterpreter return bool? new Interpreter to be
191            added ? hmm ... this however is quite suboptimal ... */
192         this->v_nextInterpreter();
193         this->parsed_ = true;
194         n = boost::next(this->self_);
195         if (n == this->impl_->interpreters_.end())
196             return ptr(0);
197     }
198     // Re-converting the Packet to a smart pointer is correct here,
199     // since the shared_ptr really uses the intrusive refcount which
200     // makes this operation safe ...
201     return ptr(n->get(),true);
202 }
203
204 prefix_ senf::Packet::ptr senf::Packet::last()
205     const
206 {
207     Packet * p = this->impl_->interpreters_.back().get();
208     while (! p->parsed_) {
209         Packet * pp = p->next().get();
210         if (pp) p = pp;
211     }
212     // Re-converting the to a smart pointer is correct here, since the
213     // shared_ptr really uses the intrusive refcount which makes this
214     // operation safe ...
215     return ptr(p,true);
216 }
217
218 prefix_ void senf::Packet::i_registerInterpreter(Packet * p)
219     const
220 {
221     BOOST_ASSERT( !p->impl_ );
222     this->impl_->truncateInterpretersAfter(this);
223     this->impl_->appendInterpreter(p);
224     this->parsed_ = true;
225 }
226
227 prefix_ void senf::Packet::i_replaceInterpreter(Packet * p)
228 {
229     BOOST_ASSERT( !p->impl_ );
230     // We need to increment the refcount of impl_ beforehand,
231     // otherwise it might get deleted by the truncateInterpreters call
232     boost::intrusive_ptr<impl::PacketImpl> impl (this->impl_,true);
233     impl->truncateInterpreters(this);
234     impl->appendInterpreter(p);
235 }
236
237 prefix_ void senf::Packet::i_setInterpreter(impl::PacketImpl * i)
238 {
239     // Using prependInterpreter makes this usable for both, the
240     // create-from-data and wrap-packet constructors
241     i->prependInterpreter(this);
242 }
243
244 prefix_ void senf::Packet::insert(iterator pos, byte v, Whence whence)
245 {
246     size_type index(pos-impl_->data_.begin());
247     BOOST_ASSERT( index >= begin_ && index <= end_);
248     impl_->data_.insert(pos,v);
249     impl_->updateIterators(index,1,self_,whence);
250 }
251
252 prefix_ void senf::Packet::insert(iterator pos, size_type n, byte v, Whence whence)
253 {
254     size_type index(pos-impl_->data_.begin());
255     BOOST_ASSERT( index >= begin_ && index <= end_ );
256     impl_->data_.insert(pos,n,v);
257     impl_->updateIterators(index,n,self_,whence);
258 }
259
260 prefix_ void senf::Packet::erase(iterator pos)
261 {
262     size_type index(pos-impl_->data_.begin());
263     BOOST_ASSERT( index >= begin_ && index < end_ );
264     impl_->data_.erase(pos);
265     impl_->updateIterators(index,-1,self_,INSIDE);
266 }
267
268 prefix_ void senf::Packet::erase(iterator first, iterator last)
269 {
270     size_type index(first-impl_->data_.begin());
271     size_type sz(last-first);
272     BOOST_ASSERT( index >= begin_ && index < end_ && sz <= end_-index );
273     /** \fixme Here we should assert, that no bytes belonging to the
274         next iterator are deleted ... */
275     impl_->data_.erase(first,last);
276     impl_->updateIterators(index,-sz,self_,INSIDE);
277 }
278
279 prefix_ void senf::Packet::dump(std::ostream & os)
280     const
281 {
282     v_dump(os);
283     ptr p (next());
284     if (p)
285         p->dump(os);
286 }
287
288 //////////////////////////////cc.e////////////////////////////////////////
289 #undef prefix_
290
291 \f
292 // Local Variables:
293 // mode: c++
294 // fill-column: 100
295 // c-file-style: "senf"
296 // indent-tabs-mode: nil
297 // ispell-local-dictionary: "american"
298 // End: