Fix documentation build under maverick (doxygen 1.7.1)
[senf.git] / senf / Packets / PacketImpl.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.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 /** \file
24     \brief PacketImpl non-inline non-template implementation */
25
26 #include "PacketImpl.ih"
27
28 // Custom includes
29 #include <iterator>
30 #include <map>
31 #include <string>
32 #include <boost/format.hpp>
33 #include <senf/Utils/String.hh>
34 #include "Packets.hh"
35
36 //#include "PacketImpl.mpp"
37 #define prefix_
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
39
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41 // senf::detail::PacketImpl
42
43 prefix_ senf::detail::PacketImpl::~PacketImpl()
44 {
45     // We increment refcount_ to ensure, release() won't call delete again
46     ++refcount_;
47     eraseInterpreters(interpreters_.begin(), interpreters_.end());
48 }
49
50 prefix_ void senf::detail::PacketImpl::release()
51 {
52     SENF_ASSERT(refcount_ >= 1, "Internal failure: Releasing dead PacketImpl ??");
53     // uah ... we need to be extremely careful here. If refcount_ is 1, we want to commit suicide,
54     // however the destructor will remove all PacketInterpreters from the list and will thereby
55     // decrement refcount -> only decrement refcount_ when *not* calling delete (otherwise
56     // the assert above will fail)
57     if (refcount_ == 1)
58         delete this;
59     else
60         -- refcount_;
61 }
62
63 // interpreter chain
64
65 prefix_ void senf::detail::PacketImpl::appendInterpreter(PacketInterpreterBase * p)
66 {
67     interpreters_.push_back(*p);
68     p->assignImpl(this);
69 }
70
71 prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase * p)
72 {
73     interpreters_.push_front(*p);
74     p->assignImpl(this);
75 }
76
77 prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase * p,
78                                                           PacketInterpreterBase * before)
79 {
80     interpreter_list::iterator i (interpreter_list::current(*before));
81     interpreters_.insert(i, *p);
82     p->assignImpl(this);
83 }
84
85 // Data container
86
87 prefix_ void senf::detail::PacketImpl::clear(PacketData * self)
88 {
89     PacketInterpreterBase * n (next(static_cast<PacketInterpreterBase*>(self)));
90     if (n)
91         truncateInterpreters(n);
92     iterator first (boost::next(begin(),self->begin_));
93     data_.erase(first, boost::next(begin(),self->end_));
94     updateIterators(self,self->begin_,-self->size());
95 }
96
97 // private members
98
99 prefix_ void senf::detail::PacketImpl::eraseInterpreters(interpreter_list::iterator b,
100                                                          interpreter_list::iterator e)
101 {
102     while (b!=e) {
103         interpreter_list::iterator i (b++);
104         PacketInterpreterBase * p (&(*i));
105         interpreters_.erase(i);
106         p->releaseImpl(); // might call PacketImpl::release and might delete p
107     }
108 }
109
110 prefix_ void senf::detail::PacketImpl::updateIterators(PacketData * self, difference_type pos,
111                                                        difference_type n)
112 {
113     // I hate to change the PacketData representation from here, I would have preferred to let
114     // PacketData have authority over this but trying that just get's to convoluted so I choose the
115     // simple solution and made PacketImpl a friend of PacketData.
116
117     interpreter_list::iterator i (interpreters_.begin());
118
119     // There are three types of packets
120     // a) Those which come before 'self' in the interpreter chain
121     // b) 'self'
122     // c) Those that come afterwards
123     // For a), the change must be inside the packet since 'self' must be within those packets
124     // For b), the change must also be within since that's the packet we are changing
125     // For c), the change must be outside the packet (we don't allow an upper packet to mess with
126     // the the data owned by a packet further down the chain). It can be before or after the
127     // packet.
128
129     // a)
130     for (; &(*i) != static_cast<PacketInterpreterBase*>(self); ++i) i->end_ += n;
131
132     // b)
133     i->end_ += n;
134
135     // c)
136     interpreter_list::iterator const i_end (interpreters_.end());
137     if (++i != i_end)
138         if (pos <= difference_type(i->begin_))
139             // pos is before the packet, it must then be before all further packets ...
140             for (; i != i_end; ++i) {
141                 i->begin_ += n;
142                 i->end_ += n;
143             }
144         // else pos is after the packet and we don't need to change anything ...
145 }
146
147 // Annotations
148
149 prefix_ void senf::detail::PacketImpl::dumpAnnotations(std::ostream & os)
150 {
151     for (AnnotationRegistry::iterator i (AnnotationRegistry::instance().begin());
152          i != AnnotationRegistry::instance().end(); ++i) {
153         void * antn (annotation(*i));
154         if (antn)
155             AnnotationRegistry::instance().dump(*i, os, antn);
156     }
157 }
158
159 prefix_ void senf::detail::PacketImpl::clearAnnotations()
160 {
161     ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
162     complexAnnotations_.clear();
163 }
164
165 prefix_ void senf::detail::PacketImpl::assignAnnotations(PacketImpl const & other)
166 {
167     std::copy(&other.simpleAnnotations_[0], &other.simpleAnnotations_[0] +
168             sizeof(simpleAnnotations_)/sizeof(simpleAnnotations_[0]), simpleAnnotations_);
169     complexAnnotations_.assign(
170             other.complexAnnotations_.begin(), other.complexAnnotations_.end());
171 }
172
173 prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_type key)
174 {
175     SENF_ASSERT( key < 0, "complexAnnotation called with invalid key");
176     return (ComplexAnnotations::size_type(-key-1) >= complexAnnotations_.size()
177             || complexAnnotations_.is_null(-key-1))
178         ? 0 : complexAnnotations_[-key-1].get();
179 }
180
181 //-/////////////////////////////////////////////////////////////////////////////////////////////////
182 // senf::detail::AnnotationRegistry
183
184 prefix_ void senf::detail::AnnotationRegistry::dump(key_type key, std::ostream & os,
185                                                     void * annotation)
186     const
187 {
188     Registry::const_iterator i (registry_.find(key));
189     if (i != registry_.end()) {
190         os << fieldName(i->second->v_name());
191         i->second->v_dump(os, annotation);
192         os << "\n";
193     }
194 }
195
196 prefix_ void senf::detail::AnnotationRegistry::dumpRegistrations(std::ostream & os)
197 {
198     boost::format fmt ("%-56.56s  %-4.4s  %-7.7s  %5d\n");
199     os << "SENF_PACKET_ANNOTATION_SLOTS = " << SENF_PACKET_ANNOTATION_SLOTS << "\n"
200        << "SENF_PACKET_ANNOTATION_SLOTSIZE = " << SENF_PACKET_ANNOTATION_SLOTSIZE << "\n";
201     os << fmt % "TYPE" % "FAST" % "COMPLEX" % "SIZE";
202
203     for (Index::const_iterator i (index_.begin()), i_end (index_.end()); i != i_end; ++i) {
204         key_type key (i->second);
205         std::string nm (i->first);
206         if (nm.size() > 56) nm.erase(nm.begin(), nm.begin()+nm.size()-32);
207         os << fmt
208             % nm
209             % (key >= 0 ? "yes" : "no")
210             % (isComplex(key) ? "yes" : "no")
211             % size(key);
212     }
213 }
214
215 prefix_ void senf::dumpPacketAnnotationRegistry(std::ostream & os)
216 {
217     senf::detail::AnnotationRegistry::instance().dumpRegistrations(os);
218 }
219
220 //-/////////////////////////////////////////////////////////////////////////////////////////////////
221 #undef prefix_
222 //#include "PacketImpl.mpp"
223
224 \f
225 // Local Variables:
226 // mode: c++
227 // fill-column: 100
228 // c-file-style: "senf"
229 // indent-tabs-mode: nil
230 // ispell-local-dictionary: "american"
231 // compile-command: "scons -u test"
232 // comment-column: 40
233 // End: