// $Id$
//
-// Copyright (C) 2006
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-// Stefan Bund <stefan.bund@fokus.fraunhofer.de>
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// Definition of non-inline non-template functions
+/** \file
+ \brief Packet non-inline non-template implementation */
-#include "Packet.hh"
-#include "Packet.ih"
+//#include "Packet.ih"
// Custom includes
-#include <boost/utility.hpp> // for next/prior
+#include "Packets.hh"
+//#include "Packet.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////
-// REFERENCE COUNTING
-///////////////////////////////////////////////////////////////////////////
-
-// We manage TWO reference counts:
-//
-// - The first reference counts lives wihin PacketImpl. It counts the
-// number of references to the PacketImpl instance
-//
-// - The second reference count lives with the Packet interpreters. It
-// counts the number of external references to the Packet facades.
-//
-// The PacketImpl refcount is always the sum of all it's Packet
-// interpreter member refcounts.
-//
-// The Packet facades are referenced from two sides:
-//
-// - From the user. These references are counted in the Packet
-// refcount.
-//
-// - From the list of interpreters. These references are *not*
-// counted.
-//
-// The Packet facades have an impl_ member. This is set to non-0 only,
-// as long as the Packet is a list member. The Packet may be deleted,
-// when impl_ == 0 and refcount_ == 0.
-
-// class ListPacketDeleter
-
-// This is the custom deleter used for the pointers in the
-// interpreters list. This deleter is only called, when the Packet is
-// removed from the interpreters list.
-prefix_ void senf::impl::ListPacketDeleter::operator()(Packet * p)
-{
- PacketImpl * impl = PacketImpl::impl(p);
- if (impl->releaseInterpreter(p))
- delete impl;
-}
-
-// struct PacketImpl
-
-prefix_ senf::Packet::interpreter_list::iterator
-senf::impl::PacketImpl::appendInterpreter(Packet * p)
-{
- BOOST_ASSERT( p->impl_ == 0 );
-
- this->refcount_ += p->refcount_;
- SATCOM_PKF_REFC_MSG("] PacketImpl::appendInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
- p->impl_ = this;
- this->interpreters_.push_back(
- boost::shared_ptr<Packet>(p, impl::ListPacketDeleter()));
-
- p->self_ = boost::prior(this->interpreters_.end());
- return p->self_;
-}
-
-prefix_ senf::Packet::interpreter_list::iterator
-senf::impl::PacketImpl::prependInterpreter(Packet * p)
-{
- BOOST_ASSERT( p->impl_ == 0 );
-
- this->refcount_ += p->refcount_;
- SATCOM_PKF_REFC_MSG("] PacketImpl::prependInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
- p->impl_ = this;
- this->interpreters_.push_front(
- boost::shared_ptr<Packet>(p, impl::ListPacketDeleter()));
-
- p->self_ = this->interpreters_.begin();
- return p->self_;
-}
-
-// Called, whenever a Packet is removed from the list by the
-// ListPacketDeleter;
-prefix_ bool senf::impl::PacketImpl::releaseInterpreter(Packet * p)
-{
- // We have to be extra careful here: This method might be called
- // AFTER the PacketImpl instance has already been destructed while
- // destructing the interpreters list !!
- // If p->refcount_ is > 0 however we know, that this->refcount_
- // must also be > 0 ...
- // So we have to make sure never to access this if p->refcount_==0
- BOOST_ASSERT( p->impl_ == this );
- bool rv (false);
- if (p->refcount_ > 0) {
- this->refcount_ -= p->refcount_;
- rv = !this->refcount_;
- SATCOM_PKF_REFC_MSG("] PacketImpl::releaseInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
- }
- if (p->unlink())
- delete p;
- return rv;
-}
-
-namespace {
- bool whenceCmp(unsigned a, unsigned b, bool end, senf::Packet::Whence whence)
- {
- using senf::Packet;
- return ((whence == Packet::OUTSIDE && ! end)
- || whence == Packet::BEFORE
- || (whence == Packet::INSIDE && end)) ? a>=b : a>b;
- }
-}
-
-prefix_ void
-senf::impl::PacketImpl::updateIterators(Packet::size_type index,
- Packet::difference_type n,
- Packet::interpreter_list::iterator self,
- Packet::Whence whence)
-{
- Packet::interpreter_list::iterator i (interpreters_.begin());
- Packet::interpreter_list::iterator const e (interpreters_.end());
- Packet::Whence w (whence == Packet::AUTO ? Packet::INSIDE : whence);
- for (;i!=e;++i) {
- if (whenceCmp((*i)->end_,index,true,w))
- if (n<0 && (*i)->end_ < index-n)
- (*i)->end_ = index;
- else
- (*i)->end_ += n;
- if (whenceCmp((*i)->begin_,index,false,w))
- if (n<0 && (*i)->begin_ < index-n)
- (*i)->begin_ = index;
- else
- (*i)->begin_ += n;
- if (i == self && whence == Packet::AUTO) w = Packet::OUTSIDE;
- BOOST_ASSERT( (*i)->end_ >= (*i)->begin_ );
- }
-}
-
-prefix_ void senf::impl::PacketImpl::packet_add_ref(Packet const * p)
-{
- p->add_ref();
- if (p->impl_)
- p->impl_->add_ref();
-}
-
-prefix_ void senf::impl::PacketImpl::packet_release(Packet * p)
-{
- bool del (p->release());
- if (p->impl_ && p->impl_->release())
- // In this case, del is certainly false here. p might
- // however get deleted now.
- delete p->impl_;
- if (del)
- delete p;
-}
-
-///////////////////////////////////////////////////////////////////////////
-// class Packet
-
-prefix_ senf::Packet::ptr senf::Packet::next()
+prefix_ senf::Packet senf::Packet::checkNext()
const
{
- interpreter_list::iterator n = boost::next(this->self_);
- if (n == this->impl_->interpreters_.end()) {
- if (this->parsed_)
- return ptr(0);
- /* \fixme v_nextInterpreter return bool? new Interpreter to be
- added ? hmm ... this however is quite suboptimal ... */
- this->v_nextInterpreter();
- this->parsed_ = true;
- n = boost::next(this->self_);
- if (n == this->impl_->interpreters_.end())
- return ptr(0);
+ PacketInterpreterBase::optional_range r (ptr()->nextPacketRange());
+ if (r && ! r->empty()) {
+ factory_t factory (ptr()->nextPacketType());
+ if (factory)
+ return parseNextAs(factory);
+ else
+ return parseNextAs<DataPacket>();
}
- // Re-converting the Packet to a smart pointer is correct here,
- // since the shared_ptr really uses the intrusive refcount which
- // makes this operation safe ...
- return ptr(n->get(),true);
+ return Packet();
}
-prefix_ senf::Packet::ptr senf::Packet::last()
+prefix_ senf::Packet senf::Packet::checkLast()
const
{
- Packet * p = this->impl_->interpreters_.back().get();
- while (! p->parsed_) {
- Packet * pp = p->next().get();
- if (pp) p = pp;
+ Packet p (*this);
+ Packet n (p.next(nothrow));
+ while (n) {
+ p = n;
+ n = p.next(nothrow);
}
- // Re-converting the to a smart pointer is correct here, since the
- // shared_ptr really uses the intrusive refcount which makes this
- // operation safe ...
- return ptr(p,true);
-}
-
-prefix_ void senf::Packet::i_registerInterpreter(Packet * p)
- const
-{
- BOOST_ASSERT( !p->impl_ );
- this->impl_->truncateInterpretersAfter(this);
- this->impl_->appendInterpreter(p);
- this->parsed_ = true;
-}
-
-prefix_ void senf::Packet::i_replaceInterpreter(Packet * p)
-{
- BOOST_ASSERT( !p->impl_ );
- // We need to increment the refcount of impl_ beforehand,
- // otherwise it might get deleted by the truncateInterpreters call
- boost::intrusive_ptr<impl::PacketImpl> impl (this->impl_,true);
- impl->truncateInterpreters(this);
- impl->appendInterpreter(p);
-}
-
-prefix_ void senf::Packet::i_setInterpreter(impl::PacketImpl * i)
-{
- // Using prependInterpreter makes this usable for both, the
- // create-from-data and wrap-packet constructors
- i->prependInterpreter(this);
-}
-
-prefix_ void senf::Packet::insert(iterator pos, byte v, Whence whence)
-{
- size_type index(pos-impl_->data_.begin());
- BOOST_ASSERT( index >= begin_ && index <= end_);
- impl_->data_.insert(pos,v);
- impl_->updateIterators(index,1,self_,whence);
-}
-
-prefix_ void senf::Packet::insert(iterator pos, size_type n, byte v, Whence whence)
-{
- size_type index(pos-impl_->data_.begin());
- BOOST_ASSERT( index >= begin_ && index <= end_ );
- impl_->data_.insert(pos,n,v);
- impl_->updateIterators(index,n,self_,whence);
-}
-
-prefix_ void senf::Packet::erase(iterator pos)
-{
- size_type index(pos-impl_->data_.begin());
- BOOST_ASSERT( index >= begin_ && index < end_ );
- impl_->data_.erase(pos);
- impl_->updateIterators(index,-1,self_,INSIDE);
-}
-
-prefix_ void senf::Packet::erase(iterator first, iterator last)
-{
- size_type index(first-impl_->data_.begin());
- size_type sz(last-first);
- BOOST_ASSERT( index >= begin_ && index < end_ && sz <= end_-index );
- /** \fixme Here we should assert, that no bytes belonging to the
- next iterator are deleted ... */
- impl_->data_.erase(first,last);
- impl_->updateIterators(index,-sz,self_,INSIDE);
-}
-
-prefix_ void senf::Packet::dump(std::ostream & os)
- const
-{
- v_dump(os);
- ptr p (next());
- if (p)
- p->dump(os);
+ return p;
}
-//////////////////////////////cc.e////////////////////////////////////////
+///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
+//#include "Packet.mpp"
\f
// Local Variables:
// mode: c++
+// fill-column: 100
// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
// End: