Implement senf::IGNORE and replace all casts-to-void with senf::IGNORE() calls
[senf.git] / senf / Packets / PacketImpl.hh
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 public header */
25
26 #ifndef HH_SENF_Packets_PacketImpl_
27 #define HH_SENF_Packets_PacketImpl_ 1
28
29 // Custom includes
30 #include <memory>
31 #include <vector>
32 #include <boost/utility.hpp>
33 #include <boost/type_traits/is_base_of.hpp>
34 #include <boost/type_traits/has_trivial_constructor.hpp>
35 #include <boost/type_traits/has_trivial_destructor.hpp>
36 #include <boost/static_assert.hpp>
37 #include <senf/Utils/pool_alloc_mixin.hh>
38 #include <senf/Utils/singleton.hh>
39
40 //#include "PacketImpl.mpp"
41 ///////////////////////////////hh.p////////////////////////////////////////
42
43 namespace senf {
44
45     /** \brief Marker base-class for complex annotations
46
47         This class is used as a base class to mark an annotation type as complex. A complex
48         annotation will have it's constructor/destructor called. Non-complex annotations will not
49         have their constructor called, they will be zero initialized. The destructor of non-complex
50         annotations is never called.
51
52         An annotation must be marked as complex if it is not <a
53         href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures">POD</a>. Simplified, an
54         annotation must be marked as ComplexAnnotation, if
55
56         \li it has a (user defined) constructor or destructor
57         \li it has any data members which have (user defined) constructors or destructors
58
59         \see \ref packet_usage_annotation
60      */
61     struct ComplexAnnotation {};
62
63 namespace detail {
64
65     struct AnnotationP
66     {
67         virtual ~AnnotationP();
68     };
69
70     template <class Annotation>
71     struct TAnnotationP
72         : public AnnotationP
73     {
74         Annotation annotation;
75     };
76
77     union AnnotationEntry {
78         AnnotationP * p;
79         unsigned long long i;
80     };
81
82     struct AnnotationIndexerBase
83     {
84         virtual ~AnnotationIndexerBase();
85         virtual void v_dump(PacketImpl * p, std::ostream & os) = 0;
86
87         static unsigned maxAnnotations;
88         static std::vector<bool> & small();
89         static std::vector<AnnotationIndexerBase*> & registry();
90         static void dump(PacketImpl * p, std::ostream & os);
91     };
92
93     template <class Annotation>
94     struct AnnotationIndexer 
95         : public senf::singleton< AnnotationIndexer<Annotation> >, 
96           public AnnotationIndexerBase
97     {
98         AnnotationIndexer();
99         virtual void v_dump(PacketImpl * p, std::ostream & os);
100         unsigned index_;
101         static unsigned index();
102         static bool const Complex = boost::is_base_of<ComplexAnnotation, Annotation>::value;
103         static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) && ! Complex);
104
105 #       if 0 // The test is difficult since it does not work with user-defined trivial constructors
106 #       ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
107
108         BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value 
109                                && boost::has_trivial_destructor<Annotation>::value)
110                               || Complex ));
111
112 #       endif
113 #       endif
114     };
115
116     template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
117     struct GetAnnotation
118     {
119         static Annotation & get(AnnotationEntry & e);
120         static void dump(AnnotationEntry & e, std::ostream & os);
121     };
122
123     template <class Annotation>
124     struct GetAnnotation<Annotation, true>
125     {
126         static Annotation & get(AnnotationEntry & e);
127         static void dump(AnnotationEntry & e, std::ostream & os);
128     };
129
130     /** \brief Internal: Packet data storage
131
132         \internal
133
134         This is the class holding the packet data and the interpreter chain. All manipulations of
135         the packet data are performed via the interface exported here. This is very important, since
136         PacketImpl will update the interpreters (that is the vector indices stored therein) whenever
137         the data is changed.
138      */
139     class PacketImpl
140         : boost::noncopyable,
141           public pool_alloc_mixin<PacketImpl>
142     {
143     public:
144         typedef senf::detail::packet::byte byte;
145         typedef senf::detail::packet::raw_container raw_container;
146         typedef senf::detail::packet::size_type size_type;
147         typedef senf::detail::packet::difference_type difference_type;
148         typedef senf::detail::packet::interpreter_list interpreter_list;
149         typedef senf::detail::packet::iterator iterator;
150         typedef senf::detail::packet::const_iterator const_iterator;
151         typedef senf::detail::packet::refcount_t refcount_t;
152
153         // structors
154
155         PacketImpl();
156         PacketImpl(size_type size, byte initValue);
157         template <class InputIterator>
158         PacketImpl(InputIterator b, InputIterator e);
159         ~PacketImpl();
160
161         // rerference/memory management
162
163         void add_ref(refcount_t n=1);
164         void release(refcount_t n=1);
165         refcount_t refcount() const;
166
167         // Interpreter chain
168
169         PacketInterpreterBase * first();
170         PacketInterpreterBase * last();
171
172         PacketInterpreterBase * next(PacketInterpreterBase * p);
173         PacketInterpreterBase * prev(PacketInterpreterBase * p);
174
175         void appendInterpreter    (PacketInterpreterBase * p);
176         void prependInterpreter   (PacketInterpreterBase * p);
177         void truncateInterpreters (PacketInterpreterBase * p);
178         void truncateInterpretersBackwards (PacketInterpreterBase * p);
179
180         // Data container
181
182         iterator begin();
183         iterator end();
184         size_type size();
185
186         void insert(PacketData * self, iterator pos, byte v);
187         void insert(PacketData * self, iterator pos, size_type n, byte v);
188         template <class ForwardIterator>
189         void insert(PacketData * self, iterator pos, ForwardIterator f, ForwardIterator l);
190
191         void erase(PacketData * self, iterator pos);
192         void erase(PacketData * self, iterator first, iterator last);
193         void clear(PacketData * self);
194
195         void reserve(size_type n);
196         size_type capacity() const;
197
198         // Annotations
199         template <class Annotation>
200         Annotation & annotation();
201         void dumpAnnotations(std::ostream & os);
202         template <class Annotation>
203         void dumpAnnotation(std::ostream & os);
204
205         /** \brief Internal: Keep PacketImpl instance alive
206
207             \internal
208
209             The Guard will keep the PacketImpl instance alive during a members execution time
210             It the refcount should drop to 0, PacketImpl will be deleted after the member
211             has completed executing.
212          */
213         struct Guard {
214             Guard(PacketImpl * impl);
215             ~Guard();
216             PacketImpl * p;
217         };
218
219     private:
220         refcount_t refcount_;
221         raw_container data_;
222         interpreter_list interpreters_;
223         
224         typedef std::vector<AnnotationEntry> Annotations;
225         Annotations annotations_;
226
227         void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
228         void updateIterators(PacketData * self, difference_type pos, difference_type n);
229     };
230
231 }}
232
233 ///////////////////////////////hh.e////////////////////////////////////////
234 #endif
235 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketImpl_i_)
236 #define HH_SENF_Packets_PacketImpl_i_
237 #include "PacketImpl.cci"
238 //#include "PacketImpl.ct"
239 #include "PacketImpl.cti"
240 #endif
241
242 \f
243 // Local Variables:
244 // mode: c++
245 // fill-column: 100
246 // c-file-style: "senf"
247 // indent-tabs-mode: nil
248 // ispell-local-dictionary: "american"
249 // compile-command: "scons -u test"
250 // comment-column: 40
251 // End:
252