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