a3b5e183c1499110b3b6445d3fed51bfbab734b3
[senf.git] / senf / Packets / SafeIterator.hh
1 // $Id$
2 //
3 // Copyright (C) 2008
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 SafeIterator public header */
25
26 #ifndef HH_SENF_Packets_SafeIterator_
27 #define HH_SENF_Packets_SafeIterator_ 1
28
29 #ifndef HH_SENF_Packets_Packets_
30 #error "Don't include 'SafeIterator.hh' directly, include 'Packets.hh'"
31 #endif
32
33 // Custom includes
34 #include <boost/iterator/iterator_facade.hpp>
35
36 //#include "SafeIterator.mpp"
37 //-/////////////////////////////////////////////////////////////////////////////////////////////////
38
39 namespace senf {
40
41     /** \brief Re-validating data iterator
42
43         This class is a wrapper around a PacketData::iterator instance. It will revalidate the
44         iterator on every access. This keeps the iterator valid even when the data container is
45         resized and thereby possibly relocated. The iterator will always point to the byte at the
46         same offset from the packets beginning. If data is inserted before this iterators position,
47         the data pointed to will of course change.
48
49         For this to work, the safe_data_iterator must be initialized with the container to which the
50         iterator belongs. After this initialization it can be used like any other iterator.
51      */
52     class safe_data_iterator
53         : public boost::iterator_facade< safe_data_iterator,
54                                          PacketData::value_type,
55                                          boost::random_access_traversal_tag >,
56           public comparable_safe_bool<safe_data_iterator>
57     {
58     public:
59         typedef PacketData::size_type size_type;
60
61         safe_data_iterator(); ///< Make uninitialized iterator
62         explicit safe_data_iterator(PacketData & data);
63                                         ///< Construct iterator only setting the data container
64         safe_data_iterator(PacketData & data, PacketData::iterator i);
65                                         ///< Initialize iterator to given position
66         explicit safe_data_iterator(PacketParserBase const & parser);
67                                         ///< Initialize iterator from parser
68                                         /**< The iterator will point to the parsers start
69                                              position. */
70
71         safe_data_iterator & operator=(PacketData::iterator i); ///< Assign iterator
72                                         /**< The iterator \a i must be from the container which \c
73                                              this iterator has been initialized. */
74         safe_data_iterator & operator=(PacketParserBase const & parser);
75                                         ///< Assign iterator from parser
76                                         /**< The iterator will point to the parser start
77                                              position. */
78
79         operator PacketData::iterator() const; ///< Convert to iterator
80
81         bool boolean_test() const;      ///< Check, if iterator is initialized
82
83         PacketData & data() const;      ///< Access data container
84
85     private:
86         friend class boost::iterator_core_access;
87
88         // iterator_facade interface
89
90         value_type & dereference() const;
91         bool equal(safe_data_iterator const & other) const;
92         difference_type distance_to(safe_data_iterator const & other) const;
93         void increment();
94         void decrement();
95         void advance(difference_type n);
96
97         PacketData::iterator i() const;
98
99         PacketData * data_;
100         size_type i_;
101     };
102
103     /** \brief Iterator re-validating Parser wrapper
104
105         An ordinary parser will be invalidated whenever the raw data container's size is
106         changed. This can complicate some algorithms considerably.
107
108         This wrapper will update the parsers iterator (the value returned by the i() member) on
109         every access. This ensures that the iterator will stay valid.
110
111         \attention Beware however, if you insert or remove data before the safe wrapper, the
112             location will \e not be updated accordingly and therefore the parser will be
113             invalid.
114
115         Additionally a SafePacketParserWrapper has an uninitialized state. The only allowed operations in
116         this state are the boolean test for validity and assigning another parser.
117
118         \ingroup packetparser
119       */
120     template <class Parser>
121     class SafePacketParserWrapper
122         : public safe_bool< SafePacketParserWrapper<Parser> >
123     {
124     public:
125         //-////////////////////////////////////////////////////////////////////////
126         // Types
127
128         //-////////////////////////////////////////////////////////////////////////
129         ///\name Structors and default members
130         //\{
131
132         // default copy constructor
133         // default copy assignment
134         // default destructor
135         SafePacketParserWrapper();             ///< Create an empty uninitialized SafePacketParserWrapper
136
137         // conversion constructors
138         SafePacketParserWrapper(Parser parser); ///< Initialize SafePacketParserWrapper from \a parser
139
140         SafePacketParserWrapper & operator=(Parser parser); ///< Assign \a parser to \c this
141
142         //\}
143         //-////////////////////////////////////////////////////////////////////////
144
145         Parser & operator*() const;       ///< Access the stored parser
146                                         /**< On every access, the stored parsers iterator will be
147                                              updated / re-validated. */
148         Parser * operator->() const; ///< Access the stored parser
149                                         /**< On every access, the stored parsers iterator will be
150                                              updated / re-validated. */
151         bool boolean_test() const;      ///< Check validity
152
153     protected:
154
155     private:
156         mutable boost::optional<Parser> parser_;
157         senf::safe_data_iterator i_;
158     };
159
160 }
161
162 //-/////////////////////////////////////////////////////////////////////////////////////////////////
163 #endif
164 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_SafeIterator_i_)
165 #define HH_SENF_Packets_SafeIterator_i_
166 #include "SafeIterator.cci"
167 //#include "SafeIterator.ct"
168 #include "SafeIterator.cti"
169 #endif
170
171 \f
172 // Local Variables:
173 // mode: c++
174 // fill-column: 100
175 // comment-column: 40
176 // c-file-style: "senf"
177 // indent-tabs-mode: nil
178 // ispell-local-dictionary: "american"
179 // compile-command: "scons -u test"
180 // End: