4bb7eeef925b0ea100d330b9f13946a17a18e343
[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 <boost/format.hpp>
31 #include <senf/Utils/String.hh>
32 #include "Packets.hh"
33
34 //#include "PacketImpl.mpp"
35 #define prefix_
36 ///////////////////////////////cc.p////////////////////////////////////////
37
38 ///////////////////////////////////////////////////////////////////////////
39 // senf::detail::PacketImpl
40
41 prefix_ senf::detail::PacketImpl::~PacketImpl()
42 {
43     // We increment refcount_ to ensure, release() won't call delete again
44     ++refcount_;
45     eraseInterpreters(interpreters_.begin(), interpreters_.end());
46 }
47
48 // interpreter chain
49
50 prefix_ void senf::detail::PacketImpl::appendInterpreter(PacketInterpreterBase * p)
51 {
52     interpreters_.push_back(*p);
53     p->assignImpl(this);
54 }
55
56 prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase * p)
57 {
58     interpreters_.push_front(*p);
59     p->assignImpl(this);
60 }
61
62 prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase * p,
63                                                           PacketInterpreterBase * before)
64 {
65     interpreter_list::iterator i (interpreter_list::current(*before));
66     interpreters_.insert(i, *p);
67     p->assignImpl(this);
68 }
69
70 // Data container
71
72 prefix_ void senf::detail::PacketImpl::clear(PacketData * self)
73 {
74     PacketInterpreterBase * n (next(static_cast<PacketInterpreterBase*>(self)));
75     if (n)
76         truncateInterpreters(n);
77     iterator first (boost::next(begin(),self->begin_));
78     data_.erase(first, boost::next(begin(),self->end_));
79     updateIterators(self,self->begin_,-self->size());
80 }
81
82 // private members
83
84 prefix_ void senf::detail::PacketImpl::eraseInterpreters(interpreter_list::iterator b,
85                                                          interpreter_list::iterator e)
86 {
87     while (b!=e) {
88         interpreter_list::iterator i (b++);
89         PacketInterpreterBase * p (&(*i));
90         interpreters_.erase(i);
91         p->releaseImpl(); // might call PacketImpl::release and might delete p
92     }
93 }
94
95 prefix_ void senf::detail::PacketImpl::updateIterators(PacketData * self, difference_type pos,
96                                                        difference_type n)
97 {
98     // I hate to change the PacketData representation from here, I would have preferred to let
99     // PacketData have authority over this but trying that just get's to convoluted so I choose the
100     // simple solution and made PacketImpl a friend of PacketData.
101
102     interpreter_list::iterator i (interpreters_.begin());
103
104     // There are three types of packets
105     // a) Those which come before 'self' in the interpreter chain
106     // b) 'self'
107     // c) Those that come afterwards
108     // For a), the change must be inside the packet since 'self' must be within those packets
109     // For b), the change must also be within since that's the packet we are changeing
110     // For c), the change must be outside the packet (we don't allow an upper packet to mess with
111     // the the data owned by a packet further down the chain). It can be before or after the
112     // packet.
113
114     // a)
115     for (; &(*i) != static_cast<PacketInterpreterBase*>(self); ++i) i->end_ += n;
116
117     // b)
118     i->end_ += n;
119
120     // c)
121     interpreter_list::iterator const i_end (interpreters_.end());
122     if (++i != i_end)
123         if (pos <= difference_type(i->begin_))
124             // pos is before the packet, it must then be before all futher packets ...
125             for (; i != i_end; ++i) {
126                 i->begin_ += n;
127                 i->end_ += n;
128             }
129         // else pos is after the packet and we don't need to change anything ...
130 }
131
132 // Annotations
133
134 prefix_ void senf::detail::PacketImpl::dumpAnnotations(std::ostream & os)
135 {
136     for (AnnotationRegistry::key_t key (AnnotationRegistry::instance().keyBegin());
137          key != AnnotationRegistry::instance().keyEnd(); ++key) {
138         void * antn (annotation(key));
139         if (antn)
140             AnnotationRegistry::instance().dump(key, os, antn);
141     }
142 }
143
144 prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_t key)
145 {
146     SENF_ASSERT( key<0, "complexAnnotation called with invalid key");
147 #ifdef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
148     return 0;
149 #else
150     while (complexAnnotations_.size() < ComplexAnnotations::size_type(-key))
151         complexAnnotations_.push_back(0);
152     if (complexAnnotations_.is_null(-key-1))
153         return 0;
154     return complexAnnotations_[-key-1].get();
155 #endif
156 }
157
158 ///////////////////////////////////////////////////////////////////////////
159 // senf::detail::AnnotationRegistry
160
161 prefix_ void senf::detail::AnnotationRegistry::dumpRegistrations(std::ostream & os)
162 {
163 #ifdef SENF_DEBUG
164     boost::format fmt ("%4.4s  %-56.56s  %-7.7s  %5d\n");
165     os << "SENF_PACKET_ANNOTATION_SLOTS = " << SENF_PACKET_ANNOTATION_SLOTS << "\n"
166        << "SENF_PACKET_ANNOTATION_SLOTSIZE = " << SENF_PACKET_ANNOTATION_SLOTSIZE << "\n";
167     os << fmt % "SLOT" % "TYPE" % "COMPLEX" % "SIZE";
168     for (key_t key (keyBegin()); key != keyEnd(); ++key) {
169         std::string nm (name(key));
170         if (nm.size() > 56) nm.erase(nm.begin(), nm.begin()+nm.size()-32);
171         os << fmt
172             % (key >= 0 ? senf::str(key) : "")
173             % nm
174             % (isComplex(key) ? "yes" : "no")
175             % size(key);
176     }
177 #endif
178 }
179
180 prefix_ void senf::dumpPacketAnnotationRegistry(std::ostream & os)
181 {
182     senf::detail::AnnotationRegistry::instance().dumpRegistrations(os);
183 }
184
185 /////////////////////////////cc.e////////////////////////////////////////
186 #undef prefix_
187 //#include "PacketImpl.mpp"
188
189 \f
190 // Local Variables:
191 // mode: c++
192 // fill-column: 100
193 // c-file-style: "senf"
194 // indent-tabs-mode: nil
195 // ispell-local-dictionary: "american"
196 // compile-command: "scons -u test"
197 // comment-column: 40
198 // End: