NEW FILE HEADER / COPYRIGHT FORMAT
[senf.git] / Packets / PacketData.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 PacketData public header */
25
26 #ifndef HH_PacketData_
27 #define HH_PacketData_ 1
28
29 // Custom includes
30 #include <boost/utility.hpp>
31 #include <boost/type_traits.hpp>
32 #include <boost/iterator/iterator_facade.hpp>
33 #include "../Utils/safe_bool.hh"
34 #include "PacketTypes.hh"
35
36 //#include "PacketData.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
38
39 namespace senf {
40
41     /** \brief Packet data STL-sequence view
42
43         The PacketData class provides an STL-sequence compatible view of the raw packet data. Each
44         packet/header/interpreter in the chain references the same storage area, presenting a
45         different (but nested/overlapping) section of the data.
46
47         Whenever the data is manipulated through PacketData, the change is assumed to be within the
48         data range of that packet: All insertions take place \e inside \c this packet and \e outside
49         any following packets in the packet chain. 
50
51         \warning It is not permissible to change data belonging to a following
52             packet/header/interpreter even though this data is part of \c this sequence. Doing so
53             will corrupt the packet data.
54         
55         \par
56
57         \warning When accessing packet data via the PacketData interface you are on your own: The
58             packet is not validated in any way, you bypass all parsers.
59
60         All public members are those of an STL random-access sequence.
61
62         \implementation This class is very tightly integrated with PacketInterpreterBase /
63             PacketInterpreter. It is separated out of those classes primarily to provide a clean
64             sequence interface to the library user and not for implementation reasons (it would have
65             been simpler to implement all these members in PacketInterpreterBase).
66
67         \ingroup packet_module
68       */
69     class PacketData
70         : boost::noncopyable
71     {
72     public:
73         ///////////////////////////////////////////////////////////////////////////
74         // Types
75
76         typedef senf::detail::packet::iterator iterator;
77         typedef senf::detail::packet::const_iterator const_iterator;
78         typedef senf::detail::packet::size_type size_type;
79         typedef senf::detail::packet::difference_type difference_type;
80         typedef senf::detail::packet::byte byte;
81         typedef byte value_type;
82         typedef byte & reference;
83         typedef byte const & const_reference;
84         typedef byte * pointer;
85         typedef byte const * const_pointer;
86
87         ///////////////////////////////////////////////////////////////////////////
88         ///\name Structors and default members
89         ///@{
90
91         // no public constructors
92         // no conversion constructors
93
94         ///@}
95         ///////////////////////////////////////////////////////////////////////////
96     
97         ///\name Sequence interface to raw data
98         ///@{
99
100         iterator begin() const; /**< Returns an <em>random access iterator</em> referring
101                                      to the first byte of the packet data. */
102         iterator end() const; /**< Returns an <em>random access iterator</em> referring to the 
103                                    element past the end of the packet data. */
104         size_type size() const; ///< Returns the number of bytes in the packet data.
105         bool empty() const; ///< Test whether the packet data is empty.
106                                         /**< Returns whether the packet data is empty, i.e. 
107                                              whether its size is 0. This function does not modify
108                                              the content of the packet data in any way. To clear
109                                              the content use clear() */        
110         byte operator[](size_type n) const;
111         byte & operator[](size_type n);
112
113         // Modifying the raw packet data
114
115         // IMPORTANT NOTE: It is not possible to insert data AFTER an empty packet
116         // since for an empty packet begin() == end(). However, I hope this problem is
117         // only academic since what should an empty packet be good for ?
118         void insert(iterator pos, byte v);
119         void insert(iterator pos, size_type n, byte v);
120 #       ifndef DOXYGEN
121         template <class InputIterator>
122         void insert(iterator pos, InputIterator f, InputIterator l,
123                     typename boost::disable_if< boost::is_convertible<InputIterator,size_type> >::type * = 0);
124 #       else
125         template <class InputIterator>
126         void insert(iterator pos, InputIterator f, InputIterator l);
127 #       endif
128
129         void erase(iterator pos);
130         void erase(iterator first, iterator last);
131         void clear(); /**< All bytes of the packet data dropped, 
132                            leaving the container with a size of 0. */
133         
134         void resize(size_type n, byte v=0);
135
136         ///@}
137
138     protected:
139         PacketData(size_type b, size_type e);
140
141         /// Need to make this protected so we can change it in the derived class
142         detail::PacketImpl * impl_;
143
144         detail::PacketImpl & impl() const;
145
146         bool valid();
147
148     private:
149         size_type begin_;
150         size_type end_;
151
152         friend class detail::PacketImpl;
153     };
154
155     class PacketParserBase;
156
157     /** \brief Invalid packet data access
158
159         This exception is signaled whenever an operation tries to access an out-of-bounds data
160         byte. If the packet has been implemented correctly, this signals a malformed packet.
161      */
162     struct TruncatedPacketException : public std::exception
163     { virtual char const * what() const throw() { return "truncated packet"; } };
164
165     /** \brief Re-validating data iterator
166
167         This class is a wrapper around a PacketData::iterator instance. It will revalidate the
168         iterator on every access. This keeps the iterator valid even when the data container is
169         resized and thereby possibly relocated. The iterator will always point to the byte at the
170         same offset from the packets beginning. If data is inserted before this iterators position,
171         the data pointed to will of course change.
172
173         For this to work, the safe_data_iterator must be initialized with the container to which the
174         iterator belongs. After this initialization it can be used like any other iterator.
175      */
176     class safe_data_iterator
177         : public boost::iterator_facade< safe_data_iterator,
178                                          PacketData::value_type,
179                                          boost::random_access_traversal_tag >,
180           public comparable_safe_bool<safe_data_iterator>
181     {
182     public:
183         typedef PacketData::size_type size_type;
184
185         safe_data_iterator(); ///< Make uninitialized iterator
186         explicit safe_data_iterator(PacketData & data); 
187                                         ///< Construct iterator only setting the data container
188         safe_data_iterator(PacketData & data, PacketData::iterator i);
189                                         ///< Initialize iterator to given position
190         explicit safe_data_iterator(PacketParserBase const & parser);
191                                         ///< Initialize iterator from parser
192                                         /**< The iterator will point to the parsers start
193                                              position. */
194
195         safe_data_iterator & operator=(PacketData::iterator i); ///< Assign iterator
196                                         /**< The iteator \a i must be from the container wo which \c
197                                              this iterator has been initialized. */
198         safe_data_iterator & operator=(PacketParserBase const & parser);
199                                         ///< Assign iterator from parser
200                                         /**< The iterator will point to the parser start
201                                              position. */
202
203         operator PacketData::iterator() const; ///< Convert to iterator
204
205         bool boolean_test() const;      ///< Check, if iterator is initialized
206
207         PacketData & data() const;      ///< Access data container
208
209     private:
210         friend class boost::iterator_core_access;
211
212         // iterator_facade interface
213
214         value_type & dereference() const;
215         bool equal(safe_data_iterator const & other) const;
216         difference_type distance_to(safe_data_iterator const & other) const;
217         void increment();
218         void decrement();
219         void advance(difference_type n);
220
221         PacketData::iterator i() const;
222
223         PacketData * data_;
224         size_type i_;
225     };
226 }
227
228 ///////////////////////////////hh.e////////////////////////////////////////
229 #endif
230 #if !defined(HH_Packets__decls_) && !defined(HH_PacketData_i_)
231 #define HH_PacketData_i_
232 #include "PacketData.cci"
233 //#include "PacketData.ct"
234 #include "PacketData.cti"
235 #endif
236
237 \f
238 // Local Variables:
239 // mode: c++
240 // fill-column: 100
241 // c-file-style: "senf"
242 // indent-tabs-mode: nil
243 // ispell-local-dictionary: "american"
244 // compile-command: "scons -u test"
245 // comment-column: 40
246 // End:
247