switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Scheduler / ReadHelper.hh
1 // $Id$
2 //
3 // Copyright (C) 2006 Stefan Bund <g0dil@berlios.de>
4 //
5 // The contents of this file are subject to the Fraunhofer FOKUS Public License
6 // Version 1.0 (the "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at 
8 // http://senf.berlios.de/license.html
9 //
10 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
11 // but modifies the Mozilla Public License Version 1.1.
12 // See the full license text for the amendments.
13 //
14 // Software distributed under the License is distributed on an "AS IS" basis, 
15 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
16 // for the specific language governing rights and limitations under the License.
17 //
18 // The Original Code is Fraunhofer FOKUS code.
19 //
20 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
21 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
22 // All Rights Reserved.
23 //
24 // Contributor(s):
25
26 // Copyright (C) 2006
27 /** \file
28     \brief ReadHelper public header */
29
30 #ifndef HH_SENF_Scheduler_ReadHelper_
31 #define HH_SENF_Scheduler_ReadHelper_ 1
32
33 // Custom includes
34 #include <string>
35 #include <boost/function.hpp>
36 #include <boost/intrusive_ptr.hpp>
37 #include <boost/scoped_ptr.hpp>
38
39 #include <senf/Utils/intrusive_refcount.hh>
40 #include "FdEvent.hh"
41
42 //#include "ReadHelper.mpp"
43 //-/////////////////////////////////////////////////////////////////////////////////////////////////
44
45 namespace senf {
46
47
48     /** \brief Asynchronous reading helper
49
50         This class provides a simple asynchronous reading facility. This helper will register with
51         the Scheduler and read incoming data. It will collect the data until a specific number of
52         bytes has been read or some Predicate evaluated on the data read thus far signals end of
53         data.
54
55         The ReadHelper accepts the same flexible file handle interfaces as the Scheduler.
56
57         The callback must take a ReadHelper::ptr argument. Using this ReadHelper instance, the
58         callback can access the data read or retrieve state information.
59
60         The ReadHelper separates the data into two parts: data() will return the matched data,
61         tail() will return any surplus data already read. If you don't specify a predicate, tail()
62         will always be empty (there may however some data be left in the socket input buffer after
63         the ReadHelper returns).
64
65         The predicate is any class instance with an <tt>operator(std::string const &)</tt>. This
66         operator is called, whenever some data has been read. If the data is not yet complete, the
67         predicate must return \c std::string::npos. If the ReadHelper should stop reading more
68         data, the predicate must return the number of bytes which are to be considered 'matched'.
69
70         \todo Move all not Handle dependent members to a ReadHandleBase class
71         \todo Add an optional <tt>std::string const & tail</tt> argument to the constructors which
72             takes the tail() of a previous ReadHelper instance.
73      */
74     template <class Handle>
75     class ReadHelper
76         : public senf::intrusive_refcount
77     {
78     public:
79         //-////////////////////////////////////////////////////////////////////////
80         // Types
81
82         typedef boost::intrusive_ptr<ReadHelper> ptr; ///< Smart pointer type for this class
83         typedef boost::function<void (ptr)> Callback; ///< Callback type
84
85         //-////////////////////////////////////////////////////////////////////////
86         ///\name Structors and default members
87         //\{
88
89         static ptr dispatch(Handle handle, std::string::size_type maxSize,
90                             Callback callback); ///< Register new ReadHandler instance
91                                         /**< The registered Callback will be called after \a maxSize
92                                              bytes have been read or EOF or some error is
93                                              encountered.
94                                              \post The returned ReadHelper instance is registered
95                                                  with the Scheduler to handle read events.
96                                              \param[in] handle file descriptor or handle providing
97                                                  the Handle interface defined above.
98                                              \param[in] maxSize maximum number of bytes to read
99                                              \param[in] callback callback
100                                              \returns Smart pointer to new ReadHelper instance */
101
102         template <class Predicate>
103         static ptr dispatch(Handle handle, std::string::size_type maxSize, Predicate const & predicate,
104                             Callback callback); ///< Register new ReadHelper instance
105                                         /**< The registered Callback will be called after the \a
106                                              predicate returns a Value other than \c
107                                              std::string::npos, \a maxSize bytes have been read, or
108                                              EOF or some error condition is encountered.
109                                              \post The returned ReadHelper instance is registered
110                                                  with the Scheduler to handle read events
111 .                                            \param[in] handle file descriptor or handle providing
112                                                  the Handle interface defined above.
113                                              \param[in] maxSize maximum number of bytes to read
114                                              \param[in] predicate predicate to check
115                                              \param[in] callback callback
116                                              \returns smart pointer to new ReadHelper instance */
117
118         //\}
119         //-////////////////////////////////////////////////////////////////////////
120
121         Handle handle() const;          ///< Access the handle object
122         std::string::size_type maxSize() const; ///< Return maximum number of bytes to be read
123
124         std::string const & data() const; ///< return data read
125         std::string const & tail() const; ///< return data read but not matched by the predicate
126
127         bool complete() const;          ///< Check whether the read has completed successfully
128         bool error() const;             ///< Check for error condition
129         void throw_error() const;       ///< If an error occurred, throw it
130
131         void revoke();                  ///< Remove the ReadHelper from the scheduler
132
133     protected:
134
135     private:
136         struct InternalPredicate;
137
138         ReadHelper(Handle handle, std::string::size_type maxSize,
139                    InternalPredicate * predicate, Callback cb);
140
141         static void dispatchProcess(ptr helper, Handle handle, int event);
142         void process(Handle handle, int event);
143         void done();
144
145         Handle handle_;
146         scheduler::FdEvent fde_;
147         std::string::size_type maxSize_;
148         boost::scoped_ptr<InternalPredicate> predicate_;
149         Callback callback_;
150
151         std::string data_;
152         std::string tail_;
153         int errno_;
154         bool complete_;
155     };
156
157     /** \brief ReadHelper predicate matching an arbitrary string
158
159         This predicate will terminate the read when the data read matches a given fixed string. All
160         data up to and including the string matched is considered to be part of the data() portion,
161         everything after the matched string is placed into the tail().
162
163         \see ReadHelper
164      */
165     struct ReadUntil
166     {
167         ReadUntil(std::string const & target);
168         std::string::size_type operator()(std::string const & data);
169         std::string target;
170     };
171
172 }
173
174 //-/////////////////////////////////////////////////////////////////////////////////////////////////
175 #include "ReadHelper.cci"
176 #include "ReadHelper.ct"
177 #include "ReadHelper.cti"
178 //#include "ReadHelper.mpp"
179 #endif
180
181 \f
182 // Local Variables:
183 // mode: c++
184 // fill-column: 100
185 // c-file-style: "senf"
186 // indent-tabs-mode: nil
187 // ispell-local-dictionary: "american"
188 // compile-command: "scons -u test"
189 // comment-column: 40
190 // End: