switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Socket / ClientSocketHandle.ct
1 // $Id$
2 //
3 // Copyright (C) 2006
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 ClientSocketHandle non-inline template implementation
30  */
31
32 #include "ClientSocketHandle.ih"
33
34 // Custom includes
35 #include <algorithm>
36 #include <boost/utility/value_init.hpp>
37 #include <senf/Utils/Buffer.hh>
38
39 #define prefix_
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43 // senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>
44
45 template <class Handle, class ForwardWritableRange, bool IsContiguous>
46 prefix_ typename boost::range_iterator<ForwardWritableRange>::type
47 senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>::
48 read(Handle & handle, ForwardWritableRange & range)
49 {
50     typename boost::range_size<ForwardWritableRange>::type nread (boost::size(range));
51     SENF_SCOPED_BUFFER(char, buffer, nread);
52     return std::copy(buffer, handle.read(buffer,buffer+nread), boost::begin(range));
53 }
54
55 template <class Handle, class ForwardWritableRange, bool IsContiguous>
56 prefix_ typename boost::range_iterator<ForwardWritableRange>::type
57 senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>::
58 readfrom(Handle & handle, ForwardWritableRange & range, typename Handle::Address & addr)
59 {
60     typename boost::range_size<ForwardWritableRange>::type nread (boost::size(range));
61     SENF_SCOPED_BUFFER(char, buffer, nread);
62     return std::copy(buffer, handle.readfrom(buffer,buffer+nread,addr), boost::begin(range));
63 }
64
65 //-/////////////////////////////////////////////////////////////////////////////////////////////////
66 // senf::detail::WriteRange<Handle,ForwardReadableRange,IsContiguous>
67
68 template <class Handle, class ForwardReadableRange, bool IsContiguous>
69 prefix_ typename boost::range_const_iterator<ForwardReadableRange>::type
70 senf::detail::WriteRange<Handle,ForwardReadableRange,IsContiguous>::
71 write(Handle & handle, ForwardReadableRange & range)
72 {
73     typename boost::range_size<ForwardReadableRange>::type nwrite (boost::size(range));
74     typename boost::range_const_iterator<ForwardReadableRange>::type i (boost::begin(range));
75     SENF_SCOPED_BUFFER(char, buffer, nwrite);
76     std::copy(i, boost::end(range), buffer);
77     std::advance(i, handle.write(std::make_pair(buffer, buffer+nwrite)) - buffer);
78     return i;
79 }
80
81 template <class Handle, class ForwardReadableRange, bool IsContiguous>
82 prefix_ typename boost::range_const_iterator<ForwardReadableRange>::type
83 senf::detail::WriteRange<Handle,ForwardReadableRange,IsContiguous>::
84 writeto(Handle & handle, ForwardReadableRange & range, typename Handle::Address const & addr)
85 {
86     typename boost::range_size<ForwardReadableRange>::type nwrite (boost::size(range));
87     typename boost::range_const_iterator<ForwardReadableRange>::type i (boost::begin(range));
88     SENF_SCOPED_BUFFER(char, buffer, nwrite);
89     std::copy(i, boost::end(range), buffer);
90     std::advance(i, handle.writeto(std::make_pair(buffer, buffer+nwrite), addr) - buffer);
91     return i;
92 }
93
94 //-/////////////////////////////////////////////////////////////////////////////////////////////////
95 // senf::ClientSocketHandle<Policy>
96
97 //-/////////////////////////////////////////////////////////////////////////////////////////////////
98 // reading and writing
99
100 // senf::ClientSocketHandle<Policy>::read
101
102 template <class SPolicy>
103 prefix_ std::string senf::ClientSocketHandle<SPolicy>::read(unsigned limit)
104 {
105     std::string rv;
106     this->read(rv, limit);
107     return rv;
108 }
109
110 template <class SPolicy>
111 template <class Sequence>
112 prefix_ void senf::ClientSocketHandle<SPolicy>::read(Sequence & container, unsigned limit)
113 {
114     if (limit == 0)
115         limit = available();
116     container.resize(limit);
117     container.erase(read( std::make_pair(container.begin(), container.end()) ),
118                     container.end());
119 }
120
121 // senf::ClientSocketHandle<SPolicy>::readfrom
122
123 template <class SPolicy>
124 prefix_ std::pair<std::string, typename SPolicy::AddressingPolicy::Address>
125 senf::ClientSocketHandle<SPolicy>::readfrom(unsigned limit)
126 {
127     std::string rv;
128     boost::value_initialized<typename SPolicy::AddressingPolicy::Address> addr;
129     this->readfrom(rv, addr.data(), limit);
130     return std::make_pair(rv, addr.data());
131 }
132
133 template <class SPolicy>
134 template <class Sequence>
135 prefix_ void senf::ClientSocketHandle<SPolicy>::readfrom(Sequence & container, Address & from,
136                                                         unsigned limit)
137 {
138     if (limit == 0)
139         limit = available();
140     container.resize(limit);
141     container.erase(readfrom( std::make_pair(container.begin(), container.end()), from ),
142                     container.end());
143 }
144
145 //-/////////////////////////////////////////////////////////////////////////////////////////////////
146 // private members
147
148 // senf::ClientSocketHandle<SPolicy>::available
149
150 template <class SPolicy>
151 prefix_ unsigned senf::ClientSocketHandle<SPolicy>::available()
152 {
153     unsigned nread = this->protocol().available();
154     if (nread == 0 && this->blocking()) {
155         // We have to block explicitly here so we can return the
156         // number of bytes available explicitly. If no more date can
157         // be expected to arive (i.e. the other end has closed the
158         // connection), the socket will always be in the readable
159         // state. This is the only case when available() will return
160         // 0.
161         this->waitReadable();
162         nread = this->protocol().available();
163     }
164     return nread;
165 }
166
167 //-/////////////////////////////////////////////////////////////////////////////////////////////////
168 #undef prefix_
169
170 \f
171 // Local Variables:
172 // mode: c++
173 // fill-column: 100
174 // c-file-style: "senf"
175 // indent-tabs-mode: nil
176 // ispell-local-dictionary: "american"
177 // compile-command: "scons -u test"
178 // comment-column: 40
179 // End: