Ipmlemented more compatible, standards conformant and flexible ClientSocketHandle...
g0dil [Fri, 8 Jun 2007 12:31:06 +0000 (12:31 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@254 270642c3-0616-0410-b53a-bc976706d245

Socket/ClientSocketHandle.ct
Socket/ClientSocketHandle.cti
Socket/ClientSocketHandle.hh
Socket/ClientSocketHandle.ih [new file with mode: 0644]
Socket/ClientSocketHandle.test.cc

index 17a518e..8e51c2b 100644 (file)
     \brief ClientSocketHandle non-inline template implementation
  */
 
-//#include "ClientSocketHandle.ih"
+#include "ClientSocketHandle.ih"
 
 // Custom includes
+#include <algorithm>
+#include "Utils/Buffer.hh"
 
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// 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>::
+read(Handle & handle, ForwardWritableRange & range)
+{
+    typename boost::range_size<ForwardWritableRange>::type nread (boost::size(range));
+    SENF_SCOPED_BUFFER(char, buffer, nread);
+    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>::
+readfrom(Handle & handle, ForwardWritableRange & range, typename Handle::Address & addr)
+{
+    typename boost::range_size<ForwardWritableRange>::type nread (boost::size(range));
+    SENF_SCOPED_BUFFER(char, buffer, nread);
+    return std::copy(buffer, handle.readfrom(buffer,buffer+nread,addr), boost::begin(range));
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ClientSocketHandle<Policy>
+
+////////////////////////////////////////
+// reading and writing
+
+// senf::ClientSocketHandle<Policy>::read
+
 template <class Policy>
 prefix_ std::string senf::ClientSocketHandle<Policy>::read(unsigned limit)
 {
@@ -40,40 +77,44 @@ prefix_ std::string senf::ClientSocketHandle<Policy>::read(unsigned limit)
 }
 
 template <class Policy>
-prefix_ void senf::ClientSocketHandle<Policy>::read(std::string & buffer, unsigned limit)
+template <class Sequence>
+prefix_ void senf::ClientSocketHandle<Policy>::read(Sequence & container, unsigned limit)
 {
-    unsigned nread = available();
+    unsigned nread (available());
     if (limit>0 && nread>limit)
         nread = limit;
-    /** \fixme This is not necessary correct and more or less a hack ... */
-    buffer.assign(nread,0);
-    unsigned rv = this->read(const_cast<char *>(buffer.data()),nread);
-    if (rv < nread)
-        buffer.erase(buffer.begin()+rv,buffer.end());
+    container.resize(nread);
+    container.erase(read( std::make_pair(container.begin(), container.end()) ), 
+                    container.end());
 }
 
+// senf::ClientSocketHandle<Policy>::readfrom
+
 template <class Policy>
 prefix_ std::pair<std::string, typename Policy::AddressingPolicy::Address>
-senf::ClientSocketHandle<Policy>::readfrom()
+senf::ClientSocketHandle<Policy>::readfrom(unsigned limit)
 {
     std::string rv;
     typename Policy::AddressingPolicy::Address addr;
-    this->readfrom(rv,addr);
+    this->readfrom(rv,addr,limit);
     return std::make_pair(rv,addr);
 }
 
 template <class Policy>
-prefix_ void senf::ClientSocketHandle<Policy>::
-readfrom(std::string & buffer, typename Policy::AddressingPolicy::Address & from)
+template <class Sequence>
+prefix_ void senf::ClientSocketHandle<Policy>::readfrom(Sequence & container, Address & from,
+                                                        unsigned limit)
 {
-    unsigned nread = available();
-    /** \fixme This is not necessary correct and more or less a hack ... */
-    buffer.assign(nread,0);
-    unsigned rv = this->readfrom(const_cast<char *>(buffer.data()), nread, from);
-    if (rv < nread)
-        buffer.erase(buffer.begin()+rv,buffer.end());
+    unsigned nread (available());
+    if (limit>0 && nread>limit)
+        nread = limit;
+    container.resize(nread);
+    container.erase(readfrom( std::make_pair(container.begin(), container.end()), from ), 
+                    container.end());
 }
 
+// senf::ClientSocketHandle<Policy>::write
+
 template <class Policy>
 prefix_ unsigned senf::ClientSocketHandle<Policy>::write(std::string const & data)
 {
@@ -95,6 +136,11 @@ prefix_ unsigned senf::ClientSocketHandle<Policy>::write(std::string const & dat
     return written;
 }
 
+////////////////////////////////////////
+// private members
+
+// senf::ClientSocketHandle<Policy>::available
+
 template <class Policy>
 prefix_ unsigned senf::ClientSocketHandle<Policy>::available()
 {
index e328d9c..8ff3396 100644 (file)
@@ -24,7 +24,7 @@
     \brief ClientSocketHandle inline template implementation
  */
 
-//#include "ClientSocketHandle.ih"
+#include "ClientSocketHandle.ih"
 
 // Custom includes
 #include <typeinfo>
 #define prefix_ inline
 ///////////////////////////////cti.p///////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// 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)));
+    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)));
+    return i + (handle.readfrom( ic, 
+                                 reinterpret_cast<char*>(storage_iterator(boost::end(range))),
+                                 addr )
+                - ic);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ClientSocketHandle<Policy>
+
+////////////////////////////////////////
+// structors
+
 template <class Policy>
 template <class OtherPolicy>
 prefix_ senf::ClientSocketHandle<Policy>::
 ClientSocketHandle(ClientSocketHandle<OtherPolicy> other,
                    typename SocketHandle<Policy>::template IsCompatible<OtherPolicy>::type *)
-    : SocketHandle<Policy>(other,true)
+    : SocketHandle<Policy>(other,true) 
 {}
 
 template <class Policy>
-prefix_ senf::ClientSocketHandle<Policy>::ClientSocketHandle(FileHandle other,
-                                                                    bool isChecked)
-    : SocketHandle<Policy>(other, isChecked)
+prefix_ senf::ClientSocketHandle<Policy>::ClientSocketHandle(FileHandle other, bool isChecked)
+    : SocketHandle<Policy>(other, isChecked) 
 {}
 
 template <class Policy>
-prefix_  senf::ClientSocketHandle<Policy>::
-ClientSocketHandle(std::auto_ptr<SocketProtocol> protocol, int fd)
-    : SocketHandle<Policy>(protocol,false)
+prefix_
+senf::ClientSocketHandle<Policy>::ClientSocketHandle(std::auto_ptr<SocketProtocol> protocol,
+                                                     int fd)
+    : SocketHandle<Policy>(protocol,false) 
 {
     this->body().fd(fd);
 }
@@ -63,32 +101,93 @@ senf::ClientSocketHandle<Policy>::operator=(ClientSocketHandle<OtherPolicy> othe
     return *this;
 }
 
-///////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////
 // reading and writing
 
+// senf::ClientSocketHandle<Policy>::read
+
 template <class Policy>
-prefix_ unsigned senf::ClientSocketHandle<Policy>::read(char * buffer,
-                                                                     unsigned size)
+template <class ForwardWritableRange>
+prefix_ typename boost::range_iterator<ForwardWritableRange>::type
+senf::ClientSocketHandle<Policy>::read(ForwardWritableRange const & range)
 {
-    return Policy::ReadPolicy::read(*this, buffer, size);
+    return detail::ReadRange< 
+        ClientSocketHandle<Policy>, 
+        ForwardWritableRange const, 
+        contiguous_storage_iterator<
+            typename boost::range_iterator<ForwardWritableRange>::type
+        >::value && sizeof(typename boost::range_value<ForwardWritableRange>::type)==sizeof(char)
+        >::read(*this, range);
 }
 
 template <class Policy>
-prefix_ unsigned senf::ClientSocketHandle<Policy>::
-readfrom(char * buffer, unsigned size, typename Policy::AddressingPolicy::Address & from)
+template <class ForwardWritableRange>
+prefix_ typename boost::range_iterator<ForwardWritableRange>::type
+senf::ClientSocketHandle<Policy>::read(ForwardWritableRange & range)
 {
-    return Policy::ReadPolicy::readfrom(*this, buffer, size, from);
+    return detail::ReadRange< 
+        ClientSocketHandle<Policy>, 
+        ForwardWritableRange, 
+        contiguous_storage_iterator<
+            typename boost::range_iterator<ForwardWritableRange>::type
+        >::value && sizeof(typename boost::range_value<ForwardWritableRange>::type)==sizeof(char)
+        >::read(*this, range);
 }
 
 template <class Policy>
+prefix_ char * senf::ClientSocketHandle<Policy>::read(char * start, char * end)
+{
+    return start + Policy::ReadPolicy::read(*this, start, end-start);
+}
+
+// senf::ClientSocketHandle<Policy>::readfrom
+
+template <class Policy>
+template <class ForwardWritableRange>
+prefix_ typename boost::range_iterator<ForwardWritableRange>::type
+senf::ClientSocketHandle<Policy>::readfrom(ForwardWritableRange const & range, Address & from)
+{
+    return detail::ReadRange< 
+        ClientSocketHandle<Policy>, 
+        ForwardWritableRange const, 
+        contiguous_storage_iterator<
+            typename boost::range_iterator<ForwardWritableRange>::type
+        >::value && sizeof(typename boost::range_value<ForwardWritableRange>::type)==sizeof(char)
+        >::readfrom(*this, range, from);
+}
+
+template <class Policy>
+template <class ForwardWritableRange>
+prefix_ typename boost::range_iterator<ForwardWritableRange>::type
+senf::ClientSocketHandle<Policy>::readfrom(ForwardWritableRange & range, Address & from)
+{
+    return detail::ReadRange< 
+        ClientSocketHandle<Policy>, 
+        ForwardWritableRange, 
+        contiguous_storage_iterator<
+            typename boost::range_iterator<ForwardWritableRange>::type
+        >::value && sizeof(typename boost::range_value<ForwardWritableRange>::type)==sizeof(char)
+        >::readfrom(*this, range, from);
+}
+
+template <class Policy>
+prefix_ char * senf::ClientSocketHandle<Policy>::readfrom(char * start, char * end,
+                                                          Address & from)
+{
+    return start + Policy::ReadPolicy::readfrom(*this, start, end-start, from);
+}
+
+// senf::ClientSocketHandle<Policy>::write
+
+template <class Policy>
 prefix_ unsigned senf::ClientSocketHandle<Policy>::write(char const * buffer,
                                                                 unsigned size)
 {
     return Policy::WritePolicy::write(*this, buffer, size);
 }
 
+// senf::ClientSocketHandle<Policy>::writeto
+
 template <class Policy>
 prefix_ unsigned senf::ClientSocketHandle<Policy>::
 writeto(typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr,
@@ -105,9 +204,11 @@ writeto(typename boost::call_traits<typename Policy::AddressingPolicy::Address>:
     return Policy::WritePolicy::writeto(*this, addr, buffer, size);
 }
 
-///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////
 // addressing
 
+// senf::ClientSocketHandle<Policy>::peer
+
 template <class Policy>
 prefix_ typename Policy::AddressingPolicy::Address
 senf::ClientSocketHandle<Policy>::peer()
@@ -124,6 +225,8 @@ peer(typename Policy::AddressingPolicy::Address & addr)
     Policy::AddressingPolicy::peer(*this,addr);
 }
 
+// senf::ClientSocketHandle<Policy>::local
+
 template <class Policy>
 prefix_ typename Policy::AddressingPolicy::Address
 senf::ClientSocketHandle<Policy>::local()
@@ -140,12 +243,16 @@ local(typename Policy::AddressingPolicy::Address & addr)
     Policy::AddressingPolicy::local(*this,addr);
 }
 
+// senf::ClientSocketHandle<Policy>::connect
+
 template <class Policy>
 prefix_ void senf::ClientSocketHandle<Policy>::connect(AddressParam addr)
 {
     Policy::AddressingPolicy::connect(*this,addr);
 }
 
+// senf::ClientSocketHandle<Policy>::bind
+
 template <class Policy>
 prefix_ void senf::ClientSocketHandle<Policy>::
 bind(typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr)
@@ -153,9 +260,11 @@ bind(typename boost::call_traits<typename Policy::AddressingPolicy::Address>::pa
     Policy::AddressingPolicy::bind(*this,addr);
 }
 
-///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////
 // Buffering
 
+// senf::ClientSocketHandle<Policy>::rcvbuf
+
 template <class Policy>
 prefix_ unsigned senf::ClientSocketHandle<Policy>::rcvbuf()
 {
@@ -168,6 +277,8 @@ prefix_ void senf::ClientSocketHandle<Policy>::rcvbuf(unsigned size)
     Policy::BufferingPolicy::rcvbuf(*this,size);
 }
 
+// senf::ClientSocketHandle<Policy>::sndbuf
+
 template <class Policy>
 prefix_ unsigned senf::ClientSocketHandle<Policy>::sndbuf()
 {
@@ -180,7 +291,8 @@ prefix_ void senf::ClientSocketHandle<Policy>::sndbuf(unsigned size)
     Policy::BufferingPolicy::sndbuf(*this,size);
 }
 
-///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////
+// Casting
 
 template <class Policy>
 prefix_ senf::ClientSocketHandle<Policy>
@@ -199,6 +311,9 @@ senf::ClientSocketHandle<Policy>::cast_dynamic(FileHandle handle)
     return cast_static(handle);
 }
 
+////////////////////////////////////////
+// State information
+
 template <class Policy>
 prefix_ void senf::ClientSocketHandle<Policy>::state(SocketStateMap & map, unsigned lod)
 {
index 29f1903..e07dccf 100644 (file)
@@ -29,6 +29,7 @@
 
 // Custom includes
 #include <boost/call_traits.hpp>
+#include <boost/range.hpp>
 #include "SocketHandle.hh"
 
 //#include "ClientSocketHandle.mpp"
@@ -139,27 +140,27 @@ namespace senf {
         /** \brief Read data from socket
 
             If the sockets \c FramingPolicy is \c DatagramFramingPolicy, every read() command will
-            return a single datagram. If the sockets FramingPolicy is StreamFraming, the operation will
-            return as much data as possible from the socket buffer. However it cannot be guaranteed,
-            that the socket buffer will be empty after read() returns.
+            return a single datagram. If the sockets FramingPolicy is StreamFraming, the operation
+            will return as much data as possible from the socket buffer. However it cannot be
+            guaranteed, that the socket buffer will be empty after read() returns.
 
             \attention If the space available for the data read is limited, the read will return no
             more than that amount of data. For a datagram socket, a full datagram is still dequeued
             from the socket buffer, the remainder of the datagram will be lost.
 
-            There are three variants of read which differ in how they return the read string.
+            There are several variants of read which differ in how they return the read string.
 
-            \throws senf::SystemException
+            If the further document doesn't tell something differently, on a blocking socket the
+            members will \e always return some data (as long as the socket has not been closed at
+            the other end) and will block, if no data is available now. If you do not want to block,
+            you \e must make the socket non-blocking (using FileHandle::blocking()).
+
+            \throws senf::SystemException 
 
 
             This variant will read up to \c limit bytes from the
             socket and return them as a \c std::string object.
 
-            On a blocking socket, this member will \e always return some data (as long as the socket
-            has not been closed at the other end) and will block, if no data is available now. If
-            you do not want to block, you \e must make the socket non-blocking (using
-            FileHandle::blocking()).
-
             \param[in] limit Maximum number of bytes to read or 0 if unlimited.
             \returns data read
 
@@ -167,55 +168,102 @@ namespace senf {
             \c recv.
         */
         std::string  read         (unsigned limit=0);
-        void         read         (std::string & buffer, unsigned limit=0);
-                                        ///< Read data into string buffer
-                                        /**< On a blocking socket, this member will \e always return
-                                           some data (as long as the socket has not been closed at
-                                           the other end) and will block, if no data is available
-                                           now. If you do not want to block, you \e must make the
-                                           socket non-blocking (using FileHandle::blocking()).
-                                           \param[out] buffer data read
-                                           \param[in] limit Maximum number of bytes to read or 0
-                                           if unlimited
-                                           \see \ref read() */
-        unsigned     read         (char * buffer, unsigned size);
+        template <class ForwardWritableRange>
+        typename boost::range_iterator<ForwardWritableRange>::type
+                     read         (ForwardWritableRange const & range);
+                                        ///< Read data into range
+                                        /**< Read data into the given range. At most
+                                             <tt>boost::size(range)</tt> characters are read. The
+                                             data read will start at the beginning of the
+                                             range. read returns a past-the-end iterator after the
+                                             last character read. This iterator will point to
+                                             somewhere within the input range.
+                                             \param[in/out] range Range to store data in 
+                                             \returns past-the-end iterator pointer to after the
+                                                 last read character 
+                                             \see \ref read() */
+        template <class ForwardWritableRange>
+        typename boost::range_iterator<ForwardWritableRange>::type
+                     read         (ForwardWritableRange & range);
+                                        ///< Read data into range
+                                        /**< \see 
+                                             read(ForwardWritableRange const &) \n
+                                             read() */
+        template <class Sequence>
+        void         read         (Sequence & container, unsigned limit);
+                                        ///< Read data into container
+                                        /**< The data read is written into the given container. Old
+                                             data in the container will be removed. For this to
+                                             work, the container must be a model of 'Sequence' as
+                                             defined in the STL documentation
+                                             \param[out] container Container to write data to
+                                             \param[in] limit Maximum number of characters to read 
+                                             \see \ref read() */
+        char *       read         (char * start, char * end);
                                         ///< Read data into memory area
-                                        /**< This variant will read data into the memory area at \c
-                                           buffer of size \c size. This is the most performant
-                                           version of read().
-                                           \param[in] buffer address of buffer to store data at
-                                           \param[in] size size of memory buffer
-                                           \returns Number of bytes read
-                                           \see \ref read() */
+                                        /**< This variant will read data into the memory area from
+                                             \a start to before \a end. This is guaranteed to be the
+                                             most efficient version  of read().
+                                             \param[in] start address of buffer to store data at
+                                             \param[in] end address one past the end of the buffer
+                                             \returns pointer past the end of the data read
+                                             \see \ref read() */
 
         /** \brief Read data from unconnected socket returning address
 
-            This member behaves like read() but should only be available, if the sockets \c
-            CommunicationPolicy is \c UnconnectedCommunicationPolicy and the \c AddressingPolicy is
-            not \c NoAddressingPolicy. The readfrom() family will in addition to the data return the
-            address of the sender.
+            The readfrom() group of member behaves like \ref read() but should only be available, if
+            the sockets \c CommunicationPolicy is \c UnconnectedCommunicationPolicy and the \c
+            AddressingPolicy is not \c NoAddressingPolicy. readfrom() will in addition to the data
+            return the address of the sender.
 
             \throws senf::SystemException
 
+
             This variant will return the data read and the address as a std::pair.
 
             \returns \c std::pair of data read (a string) and the peers address
 
-            \fixme Add \c limit argument
-
             \implementation The readfrom() family of members will use \c recvfrom from the BSD
             socket API.
          */
         std::pair<std::string, Address>
-                     readfrom     ();
-        void         readfrom     (std::string & buffer, Address & from);
-                                        ///< Read data into string buffer
-                                        /**< This variant will return the result in the locations
-                                           passed in
-                                           \param[out] buffer data read
-                                           \param[out] from peer address
-                                           \see \ref readfrom() */
-        unsigned     readfrom     (char * buffer, unsigned size, Address & from);
+                     readfrom     (unsigned limit=0);
+        template <class ForwardWritableRange>
+        typename boost::range_iterator<ForwardWritableRange>::type
+                     readfrom     (ForwardWritableRange const & range, Address & from);
+                                        ///< Read data into range
+                                        /**< Read data into the given range. At most
+                                             <tt>boost::size(range)</tt> characters are read. The
+                                             data read will start at the beginning of the
+                                             range. read returns a past-the-end iterator after the
+                                             last character read. This iterator will point to
+                                             somewhere within the input range.
+                                             \param[in/out] range Range to store data in 
+                                             \param[out] from peers address from which the data was
+                                                 received
+                                             \returns past-the-end iterator pointer to after the
+                                                 last read character 
+                                             \see \ref readfrom() */
+        template <class ForwardWritableRange>
+        typename boost::range_iterator<ForwardWritableRange>::type
+                     readfrom     (ForwardWritableRange & range, Address & from);
+                                        ///< Read data into range
+                                        /**< \see 
+                                             readfrom(ForwardWritableRange const&,Address&) \n
+                                             readfrom() */
+        template <class Sequence>
+        void         readfrom     (Sequence & container, Address & from, unsigned limit);
+                                        ///< Read data into container
+                                        /**< The data read is written into the given container. Old
+                                             data in the container will be removed. For this to
+                                             work, the container must be a model of 'Sequence' as
+                                             defined in the STL documentation
+                                             \param[out] container Container to write data to
+                                             \param[in] limit Maximum number of characters to read 
+                                             \param[out] from peers address from which the data was
+                                                 received
+                                             \see \ref readfrom() */
+        char *       readfrom     (char * start, char * end, Address & from);
                                         ///< Read data into memory buffer
                                         /**< This variant will read data into the memory area at \c
                                            buffer of size \c size. This is the most performant
diff --git a/Socket/ClientSocketHandle.ih b/Socket/ClientSocketHandle.ih
new file mode 100644 (file)
index 0000000..f3a9c4b
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief ClientSocketHandle internal header */
+
+#ifndef IH_ClientSocketHandle_
+#define IH_ClientSocketHandle_ 1
+
+// Custom includes
+#include "Utils/IteratorTraits.hh"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace detail {
+
+    template <class Handle, class ForwardWritableRange, bool IsContiguous>
+    struct ReadRange 
+    {
+        static typename boost::range_iterator<ForwardWritableRange>::type
+        read(Handle & handle, ForwardWritableRange & range);
+
+        static typename boost::range_iterator<ForwardWritableRange>::type
+        readfrom(Handle & handle, ForwardWritableRange & range, typename Handle::Address & addr);
+    };
+
+    template <class Handle, class ForwardWritableRange>
+    struct ReadRange<Handle,ForwardWritableRange,true>
+    {
+        static typename boost::range_iterator<ForwardWritableRange>::type
+        read(Handle & handle, ForwardWritableRange & range);
+
+        static typename boost::range_iterator<ForwardWritableRange>::type
+        readfrom(Handle & handle, ForwardWritableRange & range, typename Handle::Address & addr);
+    };
+
+}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// End:
index 816573b..b303951 100644 (file)
@@ -87,13 +87,13 @@ BOOST_AUTO_UNIT_TEST(clientSocketHandle)
     BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.read(), "TEST-READ" ) );
     {
         std::string buf("FOO-BAR");
-        BOOST_CHECK_NO_THROW( myh.read(buf) );
+        BOOST_CHECK_NO_THROW( myh.read(buf,0) );
         BOOST_CHECK_EQUAL( buf, "TEST-READ" );
     }
     {
         char buf[11];
         ::strcpy(buf,"0123456789");
-        BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.read(buf,10), 9u ) );
+        BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.read(buf,buf+10), buf+9u ) );
         BOOST_CHECK_EQUAL( buf, "TEST-READ9" );
     }
 
@@ -101,14 +101,14 @@ BOOST_AUTO_UNIT_TEST(clientSocketHandle)
     {
         std::string buf("FOO-BAR");
         unsigned addr;
-        BOOST_CHECK_NO_THROW( myh.readfrom(buf,addr) );
+        BOOST_CHECK_NO_THROW( myh.readfrom(buf,addr,0) );
         BOOST_CHECK_EQUAL( buf, "TEST-READ" );
     }
     {
         char buf[11];
         unsigned addr;
         ::strcpy(buf,"0123456789");
-        BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.readfrom(buf,10,addr), 9u ) );
+        BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.readfrom(buf,buf+10,addr), buf+9u ) );
         BOOST_CHECK_EQUAL( buf, "TEST-READ9" );
     }