///////////////////////////////////////////////////////////////////////////
// senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>
-// senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>::read
-
template <class Handle, class ForwardWritableRange, bool IsContiguous>
prefix_ typename boost::range_iterator<ForwardWritableRange>::type
senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>::
return std::copy(buffer, handle.read(buffer,buffer+nread), boost::begin(range));
}
-// senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>::readfrom
-
template <class Handle, class ForwardWritableRange, bool IsContiguous>
prefix_ typename boost::range_iterator<ForwardWritableRange>::type
senf::detail::ReadRange<Handle,ForwardWritableRange,IsContiguous>::
}
///////////////////////////////////////////////////////////////////////////
+// senf::detail::WriteRange<Handle,ForwardReadableRange,IsContiguous>
+
+template <class Handle, class ForwardReadableRange, bool IsContiguous>
+prefix_ typename boost::range_iterator<ForwardReadableRange>::type
+senf::detail::WriteRange<Handle,ForwardReadableRange,IsContiguous>::
+write(Handle & handle, ForwardReadableRange & range)
+{
+ typename boost::range_size<ForwardReadableRange>::type nwrite (boost::size(range));
+ SENF_SCOPED_BUFFER(char, buffer, nwrite);
+ std::copy(boost::begin(range), boost::end(range), buffer);
+ return handle.write(std::make_pair(buffer, buffer+nwrite));
+}
+
+template <class Handle, class ForwardReadableRange, bool IsContiguous>
+prefix_ typename boost::range_iterator<ForwardReadableRange>::type
+senf::detail::WriteRange<Handle,ForwardReadableRange,IsContiguous>::
+writeto(Handle & handle, ForwardReadableRange & range, typename Handle::Address const & addr)
+{
+ typename boost::range_size<ForwardReadableRange>::type nwrite (boost::size(range));
+ SENF_SCOPED_BUFFER(char, buffer, nwrite);
+ std::copy(boost::begin(range), boost::end(range), buffer);
+ return handle.writeto(std::make_pair(buffer, buffer+nwrite), addr);
+}
+
+///////////////////////////////////////////////////////////////////////////
// senf::ClientSocketHandle<Policy>
////////////////////////////////////////
container.end());
}
-// senf::ClientSocketHandle<Policy>::write
-
-template <class Policy>
-prefix_ unsigned senf::ClientSocketHandle<Policy>::write(std::string const & data)
-{
- unsigned written = this->write(data.data(),data.size());
- if (written == 0)
- throw SystemException(EPIPE);
- // This implementation ensures, we only call blocking() when
- // necessary (since it incurs a system call overhead ...)
- if (written < data.size() && this->blocking())
- // We need to enforce in the WritePolicy implementation, that
- // DatagramFramingPolicy sockets will ALWAYS either write the
- // complete datagram or nothing at all
- while (written < data.size()) {
- unsigned n = this->write(data.data()+written,data.size()-written);
- if (n == 0)
- throw SystemException(EPIPE);
- written += n;
- }
- return written;
-}
-
////////////////////////////////////////
// private members
///////////////////////////////////////////////////////////////////////////
// senf::detail::ReadRange<Policy,ForwardWritableRange,true>
-// senf::detail::ReadRange<Policy,ForwardWritableRange,true>::read
-
template <class Handle, class ForwardWritableRange>
prefix_ typename boost::range_iterator<ForwardWritableRange>::type
senf::detail::ReadRange<Handle,ForwardWritableRange,true>::read(Handle & handle,
ForwardWritableRange & range)
{
- typename boost::range_iterator<ForwardWritableRange>::type i (boost::begin(range));
- char * ic (reinterpret_cast<char*>(storage_iterator(i)));
+ typename boost::range_iterator<ForwardWritableRange>::type const i (boost::begin(range));
+ char * const ic (reinterpret_cast<char*>(storage_iterator(i)));
return i + (handle.read( ic,
reinterpret_cast<char*>(storage_iterator(boost::end(range))) )
- ic);
}
-// senf::detail::ReadRange<Policy,ForwardWritableRange,true>::readfrom
-
template <class Handle, class ForwardWritableRange>
prefix_ typename boost::range_iterator<ForwardWritableRange>::type
senf::detail::ReadRange<Handle,ForwardWritableRange,true>::
readfrom(Handle & handle, ForwardWritableRange & range, typename Handle::Address & addr)
{
- typename boost::range_iterator<ForwardWritableRange>::type i (boost::begin(range));
- char * ic (reinterpret_cast<char*>(storage_iterator(i)));
+ typename boost::range_iterator<ForwardWritableRange>::type const i (boost::begin(range));
+ char * const ic (reinterpret_cast<char*>(storage_iterator(i)));
return i + (handle.readfrom( ic,
reinterpret_cast<char*>(storage_iterator(boost::end(range))),
addr )
}
///////////////////////////////////////////////////////////////////////////
+// senf::detail::WriteRange<Handle, ForwardReadableRange, true>
+
+template <class Handle, class ForwardReadableRange>
+prefix_ typename boost::range_const_iterator<ForwardReadableRange>::type
+senf::detail::WriteRange<Handle, ForwardReadableRange, true>::
+write(Handle & handle, ForwardReadableRange & range)
+{
+ typename boost::range_const_iterator<ForwardReadableRange>::type const i
+ (boost::const_begin(range));
+ char const * const ic (reinterpret_cast<char const *>(storage_iterator(i)));
+ return i + (handle.write(ic,
+ reinterpret_cast<char const *>(
+ storage_iterator(boost::const_end(range))))
+ - ic);
+}
+
+template <class Handle, class ForwardReadableRange>
+prefix_ typename boost::range_const_iterator<ForwardReadableRange>::type
+senf::detail::WriteRange<Handle, ForwardReadableRange, true>::
+writeto(Handle & handle, ForwardReadableRange & range, typename Handle::Address const & addr)
+{
+ typename boost::range_const_iterator<ForwardReadableRange>::type const i
+ (boost::const_begin(range));
+ char const * const ic (reinterpret_cast<char const *>(storage_iterator(i)));
+ return i + (handle.writeto(addr,
+ ic,
+ reinterpret_cast<char const *>(
+ storage_iterator(boost::const_end(range))))
+ - ic);
+}
+
+///////////////////////////////////////////////////////////////////////////
// senf::ClientSocketHandle<Policy>
////////////////////////////////////////
template <class Policy>
template <class ForwardWritableRange>
-prefix_ typename boost::range_iterator<ForwardWritableRange>::type
+prefix_ typename boost::range_iterator<ForwardWritableRange const>::type
senf::ClientSocketHandle<Policy>::readfrom(ForwardWritableRange const & range, Address & from)
{
return detail::ReadRange<
// senf::ClientSocketHandle<Policy>::write
template <class Policy>
-prefix_ unsigned senf::ClientSocketHandle<Policy>::write(char const * buffer,
- unsigned size)
+template <class ForwardReadableRange>
+prefix_ typename boost::range_const_iterator<ForwardReadableRange const>::type
+senf::ClientSocketHandle<Policy>::write(ForwardReadableRange const & range)
{
- return Policy::WritePolicy::write(*this, buffer, size);
+ return detail::WriteRange<
+ ClientSocketHandle<Policy>,
+ ForwardReadableRange const,
+ contiguous_storage_iterator<
+ typename boost::range_iterator<ForwardReadableRange>::type
+ >::value && sizeof(typename boost::range_value<ForwardReadableRange>::type)==sizeof(char)
+ >::write(*this, range);
+}
+
+template <class Policy>
+prefix_ char const * senf::ClientSocketHandle<Policy>::write(char const * start, char const * end)
+{
+ return start + Policy::WritePolicy::write(*this, start, end-start);
}
// senf::ClientSocketHandle<Policy>::writeto
template <class Policy>
-prefix_ unsigned senf::ClientSocketHandle<Policy>::
-writeto(typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr,
- std::string const & data)
+template <class ForwardReadableRange>
+prefix_ typename boost::range_const_iterator<ForwardReadableRange const>::type
+senf::ClientSocketHandle<Policy>::writeto(AddressParam addr, ForwardReadableRange const & range)
{
- return this->writeto(addr, data.data(), data.size());
+ return detail::WriteRange<
+ ClientSocketHandle<Policy>,
+ ForwardReadableRange const,
+ contiguous_storage_iterator<
+ typename boost::range_iterator<ForwardReadableRange>::type
+ >::value && sizeof(typename boost::range_value<ForwardReadableRange>::type)==sizeof(char)
+ >::writeto(*this, range, addr);
}
template <class Policy>
-prefix_ unsigned senf::ClientSocketHandle<Policy>::
-writeto(typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr,
- char const * buffer, unsigned size)
+prefix_ char const * senf::ClientSocketHandle<Policy>::writeto(AddressParam addr,
+ char const * start,
+ char const * end)
{
- return Policy::WritePolicy::writeto(*this, addr, buffer, size);
+ return start + Policy::WritePolicy::writeto(*this, addr, start, end-start);
}
////////////////////////////////////////
std::pair<std::string, Address>
readfrom (unsigned limit=0);
template <class ForwardWritableRange>
- typename boost::range_iterator<ForwardWritableRange>::type
+ typename boost::range_iterator<ForwardWritableRange const>::type
readfrom (ForwardWritableRange const & range, Address & from);
///< Read data into range
/**< Read data into the given range. At most
\throws senf::SystemException
- This variant will write out the string \c data.
+ This variant will write out the range \c data.
- \param[in] data Data to write
- \returns number of bytes written
+ \param[in] range Data to write
+ \returns past-the-end iterator after last element written
\implementation The write() family of members will use POSIX \c write calls, not \c
send.
*/
- unsigned write (std::string const & data);
- unsigned write (char const * buffer, unsigned size);
+ template <class ForwardReadableRange>
+ typename boost::range_const_iterator<ForwardReadableRange const>::type
+ write (ForwardReadableRange const & range);
+ char const * write (char const * start, char const * end);
///< Write data to socket from memory buffer
- /**< \param[in] buffer address of buffer to write
- \param[in] size amount of data to write
- \returns Number of bytes written
- \see \ref write() */
+ /**< \param[in] start beginning of area to write
+ \param[in] end past-the-end pointer to area to write
+ \returns past-the-end pointer after last byte written
+ \see \ref write() */
/** \brief Write data to unconnected socket
\throw senf::SystemException
- This variant will send the string \c data to the peer \c addr.
+ This variant will send the range \c range to peer \c addr.
\param[in] addr Address of peer to send data to
- \param[in] data data to send
+ \param[in] range data to send
\returns Number of bytes written
*/
- unsigned writeto (AddressParam addr, std::string const & data);
- unsigned writeto (AddressParam addr, char const * buffer, unsigned size);
+ template <class ForwardReadableRange>
+ typename boost::range_const_iterator<ForwardReadableRange const>::type
+ writeto (AddressParam addr, ForwardReadableRange const & range);
+ char const * writeto (AddressParam addr, char const * start, char const * end);
///< Write data from memory buffer to unconnected socket
/**< \param[in] addr Address of peer to send data to
- \param[in] buffer address of buffer to write
- \param[in] size amount of data to write
- \returns Number of bytes written
- \see \ref writeto() */
+ \param[in] start address of buffer to write
+ \param[in] end past-the-end pointer after data to write
+ \returns past-the-end iterator after last byte written
+ \see \ref writeto() */
///////////////////////////////////////////////////////////////////////////
///\name Addressing
namespace senf {
namespace detail {
+ ///////////////////////////////////////////////////////////////////////
+ // senf::detail::ReadRange
+
template <class Handle, class ForwardWritableRange, bool IsContiguous>
struct ReadRange
{
};
template <class Handle, class ForwardWritableRange>
- struct ReadRange<Handle,ForwardWritableRange,true>
+ struct ReadRange<Handle, ForwardWritableRange, true>
{
static typename boost::range_iterator<ForwardWritableRange>::type
read(Handle & handle, ForwardWritableRange & range);
readfrom(Handle & handle, ForwardWritableRange & range, typename Handle::Address & addr);
};
+ ///////////////////////////////////////////////////////////////////////
+ // senf::detail::WriteRange
+
+ template <class Handle, class ForwardReadableRange, bool IsContiguous>
+ struct WriteRange
+ {
+ static typename boost::range_iterator<ForwardReadableRange>::type
+ write(Handle & handle, ForwardReadableRange & range);
+
+ static typename boost::range_iterator<ForwardReadableRange>::type
+ writeto(Handle & handle, ForwardReadableRange & range,
+ typename Handle::Address const & addr);
+ };
+
+ template <class Handle, class ForwardReadableRange>
+ struct WriteRange<Handle, ForwardReadableRange, true>
+ {
+ static typename boost::range_const_iterator<ForwardReadableRange>::type
+ write(Handle & handle, ForwardReadableRange & range);
+
+ static typename boost::range_const_iterator<ForwardReadableRange>::type
+ writeto(Handle & handle, ForwardReadableRange & range,
+ typename Handle::Address const & addr);
+ };
+
}}
///////////////////////////////ih.e////////////////////////////////////////
{
char buf[11];
::strcpy(buf,"0123456789");
- BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.read(buf,buf+10), buf+9u ) );
+ BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.read(buf,buf+10), buf+9 ) );
BOOST_CHECK_EQUAL( buf, "TEST-READ9" );
}
char buf[11];
unsigned addr;
::strcpy(buf,"0123456789");
- BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.readfrom(buf,buf+10,addr), buf+9u ) );
+ BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.readfrom(buf,buf+10,addr), buf+9 ) );
BOOST_CHECK_EQUAL( buf, "TEST-READ9" );
}
- BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.write("TEST-WRITE"), 10u ) );
- BOOST_CHECK_THROW( myh.write("TEST"),senf::SystemException );
- BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.write("TEST-WRITE9",10), 10u ) );
- BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.writeto(0,"TEST-WRITE"), 10u ) );
- BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.writeto(0,"TEST-WRITE9",10), 10u ) );
+ {
+ std::string s ("TEST-WRITE");
+ BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.write(s)-s.begin(), 10 ) );
+ s = "TEST";
+ // This simulates a closed file in this test policy. However, we
+ // have changed the semantics so this will not work anymore.
+ // BOOST_CHECK_THROW( myh.write(s),senf::SystemException );
+ char const * const s1 = "TEST-WRITE9";
+ BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.write(s1,s1+10), s1+10u ) );
+ s = "TEST-WRITE";
+ BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.writeto(0,s)-s.begin(), 10 ) );
+ BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.writeto(0,s1,s1+10), s1+10 ) );
+ }
BOOST_CHECK_NO_THROW( myh.connect(0) );
BOOST_CHECK_NO_THROW( myh.bind(0) );
template <class Policy>
static unsigned readfrom(ClientSocketHandle<Policy> handle, char * buffer, unsigned size,
typename Policy::AddressingPolicy::Address & address,
- typename IfCommunicationPolicyIs<Policy,UnconnectedCommunicationPolicy>::type * = 0);
+ typename IfCommunicationPolicyIs<
+ Policy,UnconnectedCommunicationPolicy>::type * = 0);
///< read data from socket returning peer address
/**< \param[in] handle socket handle to read from
\param[in] buffer address of buffer to write data to
{
template <class Policy>
static unsigned write(ClientSocketHandle<Policy> handle, char const * buffer, unsigned size,
- typename IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type * = 0);
+ typename IfCommunicationPolicyIs<
+ Policy,ConnectedCommunicationPolicy>::type * = 0);
///< write data to socket
/**< This member is only enabled if the socket uses
connected communication. Otherwise the communication
\returns number of bytes written */
template <class Policy>
static unsigned writeto(ClientSocketHandle<Policy> handle,
- typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr,
+ typename boost::call_traits<
+ typename Policy::AddressingPolicy::Address>::param_type addr,
char const * buffer, unsigned size,
- typename IfCommunicationPolicyIs<Policy,UnconnectedCommunicationPolicy>::type * = 0);
+ typename IfCommunicationPolicyIs<
+ Policy,UnconnectedCommunicationPolicy>::type * = 0);
///< write data to socket sending to given peer
/**< This member is only enabled if the socket uses
unconnected communication. Otherwise no target may be
BOOST_CHECK_EQUAL( sock.rcvbuf(), 2048u );
BOOST_CHECK_NO_THROW( sock.sndbuf(2048) );
BOOST_CHECK_EQUAL( sock.sndbuf(), 2048u );
- BOOST_CHECK_NO_THROW( sock.writeto("127.0.0.1:12345","TEST-WRITE") );
+ BOOST_CHECK_NO_THROW( sock.writeto("127.0.0.1:12345", std::string("TEST-WRITE")) );
BOOST_CHECK_EQUAL( sock.read(), "TEST-WRITE" );
BOOST_CHECK_NO_THROW( sock.protocol().timestamp() );
sock.writeto("127.0.0.1:12345","QUIT");