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