Skip to content
Snippets Groups Projects
Commit 639bf7c4 authored by g0dil's avatar g0dil
Browse files

Ipmlemented more compatible, standards conformant and flexible...

Ipmlemented more compatible, standards conformant and flexible ClientSocketHandle::read() and readfrom() members
parent 3c7a6e25
No related branches found
No related tags found
No related merge requests found
......@@ -24,13 +24,50 @@
\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()
{
......
......@@ -24,7 +24,7 @@
\brief ClientSocketHandle inline template implementation
*/
//#include "ClientSocketHandle.ih"
#include "ClientSocketHandle.ih"
// Custom includes
#include <typeinfo>
......@@ -32,24 +32,62 @@
#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,25 +101,84 @@ 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)
......@@ -89,6 +186,8 @@ prefix_ unsigned senf::ClientSocketHandle<Policy>::write(char const * buffer,
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)
{
......
......@@ -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
......
// 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
// Local Variables:
// mode: c++
// fill-column: 100
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// End:
......@@ -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" );
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment