2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
22 \brief PacketData public header */
24 #ifndef HH_PacketData_
25 #define HH_PacketData_ 1
28 #include <boost/utility.hpp>
29 #include <boost/type_traits.hpp>
30 #include <boost/iterator/iterator_facade.hpp>
31 #include "Utils/SafeBool.hh"
32 #include "PacketTypes.hh"
34 //#include "PacketData.mpp"
35 ///////////////////////////////hh.p////////////////////////////////////////
39 /** \brief Packet data STL-sequence view
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.
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.
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.
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.
58 All public members are those of an STL random-access sequence.
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).
65 \ingroup packet_module
71 ///////////////////////////////////////////////////////////////////////////
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;
85 ///////////////////////////////////////////////////////////////////////////
86 ///\name Structors and default members
89 // no public constructors
90 // no conversion constructors
93 ///////////////////////////////////////////////////////////////////////////
95 ///\name Sequence interface to raw data
98 iterator begin() const;
100 size_type size() const;
102 byte operator[](size_type n) const;
103 byte & operator[](size_type n);
105 // Modifying the raw packet data
107 // IMPORTANT NOTE: It is not possible to insert data AFTER an empty packet
108 // since for an empty packet begin() == end(). However, I hope this problem is
109 // only academic since what should an empty packet be good for ?
110 void insert(iterator pos, byte v);
111 void insert(iterator pos, size_type n, byte v);
113 template <class InputIterator>
114 void insert(iterator pos, InputIterator f, InputIterator l,
115 typename boost::disable_if< boost::is_convertible<InputIterator,size_type> >::type * = 0);
117 template <class InputIterator>
118 void insert(iterator pos, InputIterator f, InputIterator l);
121 void erase(iterator pos);
122 void erase(iterator first, iterator last);
125 void resize(size_type n, byte v=0);
130 PacketData(size_type b, size_type e);
132 /// Need to make this protected so we can change it in the derived class
133 detail::PacketImpl * impl_;
135 detail::PacketImpl & impl() const;
143 friend class detail::PacketImpl;
146 class PacketParserBase;
148 /** \brief Invalid packet data access
150 This exception is signaled whenever an operation tries to access an out-of-bounds data
151 byte. If the packet has been implemented correctly, this signals a malformed packet.
153 struct TruncatedPacketException : public std::exception
154 { virtual char const * what() const throw() { return "truncated packet"; } };
156 /** \brief Re-validating data iterator
158 This class is a wrapper around a PacketData::iterator instance. It will revalidate the
159 iterator on every access. This keeps the iterator valid even when the data container is
160 resized and thereby possibly relocated. The iterator will always point to the byte at the
161 same offset from the packets beginning. If data is inserted before this iterators position,
162 the data pointed to will of course change.
164 For this to work, the safe_data_iterator must be initialized with the container to which the
165 iterator belongs. After this initialization it can be used like any other iterator.
167 class safe_data_iterator
168 : public boost::iterator_facade< safe_data_iterator,
169 PacketData::value_type,
170 boost::random_access_traversal_tag >,
171 public ComparableSafeBool<safe_data_iterator>
174 typedef PacketData::size_type size_type;
176 safe_data_iterator(); ///< Make uninitialized iterator
177 explicit safe_data_iterator(PacketData & data);
178 ///< Construct iterator only setting the data container
179 safe_data_iterator(PacketData & data, PacketData::iterator i);
180 ///< Initialize iterator to given position
181 explicit safe_data_iterator(PacketParserBase const & parser);
182 ///< Initialize iterator from parser
183 /**< The iterator will point to the parsers start
186 safe_data_iterator & operator=(PacketData::iterator i); ///< Assign iterator
187 /**< The iteator \a i must be from the container wo which \c
188 this iterator has been initialized. */
189 safe_data_iterator & operator=(PacketParserBase const & parser);
190 ///< Assign iterator from parser
191 /**< The iterator will point to the parser start
194 operator PacketData::iterator() const; ///< Convert to iterator
196 bool boolean_test() const; ///< Check, if iterator is initialized
198 PacketData & data() const; ///< Access data container
201 friend class boost::iterator_core_access;
203 // iterator_facade interface
205 value_type & dereference() const;
206 bool equal(safe_data_iterator const & other) const;
207 difference_type distance_to(safe_data_iterator const & other) const;
210 void advance(difference_type n);
212 PacketData::iterator i() const;
219 ///////////////////////////////hh.e////////////////////////////////////////
221 #if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketData_i_)
222 #define HH_PacketData_i_
223 #include "PacketData.cci"
224 //#include "PacketData.ct"
225 #include "PacketData.cti"
232 // c-file-style: "senf"
233 // indent-tabs-mode: nil
234 // ispell-local-dictionary: "american"
235 // compile-command: "scons -u test"
236 // comment-column: 40