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