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