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