more test utils
This commit is contained in:
@@ -337,6 +337,7 @@ bool EvOutBuf::refill(size_t more)
|
||||
bool EvInBuf::refill(size_t more)
|
||||
{
|
||||
if(err) return false;
|
||||
size_t len = size(); // unconsumed before request
|
||||
|
||||
if(base && evbuffer_drain(backing, pos-base))
|
||||
throw std::bad_alloc();
|
||||
@@ -344,8 +345,13 @@ bool EvInBuf::refill(size_t more)
|
||||
limit = base = pos = nullptr;
|
||||
|
||||
if(more) {
|
||||
// ensure new segment contains at least the requested size (one element)
|
||||
// (we hope this is mostly a no-op)
|
||||
(void)evbuffer_pullup(backing, len+more);
|
||||
|
||||
evbuffer_iovec vec;
|
||||
|
||||
// peek at the next segment
|
||||
auto n = evbuffer_peek(backing, -1, nullptr, &vec, 1);
|
||||
if(n<=0) { // current (2.1) impl never returns negative
|
||||
return false;
|
||||
@@ -353,6 +359,10 @@ bool EvInBuf::refill(size_t more)
|
||||
|
||||
base = pos = (uint8_t*)vec.iov_base;
|
||||
limit = base+vec.iov_len;
|
||||
|
||||
if(size() < len+more) {
|
||||
return false; // pullup didn't work.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+18
-1
@@ -59,6 +59,7 @@ public:
|
||||
pos = limit;
|
||||
i -= size();
|
||||
} while(static_cast<Subclass*>(this)->refill(i));
|
||||
fault();
|
||||
}
|
||||
|
||||
EPICS_ALWAYS_INLINE bool empty() const { return limit==pos; }
|
||||
@@ -305,7 +306,7 @@ inline void _to_wire(Buf& buf, const uint8_t *mem, bool reverse)
|
||||
* @param buf output buffer. buf[0] through buf[sizeof(T)-1] must be valid.
|
||||
* @param val input variable
|
||||
*/
|
||||
template<typename T, typename Buf, typename std::enable_if<std::is_scalar<T>::value, int>::type =0>
|
||||
template<typename T, typename Buf, typename std::enable_if<sizeof(T)>=2 && std::is_scalar<T>{} && !std::is_pointer<T>{}, int>::type =0>
|
||||
inline void to_wire(Buf& buf, const T& val)
|
||||
{
|
||||
union {
|
||||
@@ -316,6 +317,16 @@ inline void to_wire(Buf& buf, const T& val)
|
||||
_to_wire<sizeof(T)>(buf, pun.b, buf.be ^ (EPICS_BYTE_ORDER==EPICS_ENDIAN_BIG));
|
||||
}
|
||||
|
||||
template<typename T, typename Buf, typename std::enable_if<sizeof(T)==1 && std::is_scalar<T>{}, int>::type =0>
|
||||
inline void to_wire(Buf& buf, const T& val)
|
||||
{
|
||||
if(!buf.ensure(1)) {
|
||||
buf.fault();
|
||||
} else {
|
||||
buf.push(val);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Buf>
|
||||
void to_wire(Buf& buf, const Size& size)
|
||||
{
|
||||
@@ -349,6 +360,12 @@ void to_wire(Buf& buf, const char *s)
|
||||
|
||||
}
|
||||
|
||||
template<typename Buf>
|
||||
inline void to_wire(Buf& buf, const std::string& s)
|
||||
{
|
||||
to_wire(buf, s.c_str());
|
||||
}
|
||||
|
||||
template<typename Buf>
|
||||
void to_wire(Buf& buf, std::initializer_list<uint8_t> bytes)
|
||||
{
|
||||
|
||||
+10
-1
@@ -13,7 +13,9 @@
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include <pvxs/version.h>
|
||||
#include <pvxs/util.h>
|
||||
@@ -57,7 +59,7 @@ public:
|
||||
namespace detail {
|
||||
|
||||
// control how testEq() and testNotEq() print things
|
||||
template<typename T>
|
||||
template<typename T, typename Enable=void>
|
||||
struct test_print {
|
||||
template<class C>
|
||||
static inline void op(C& strm, const T& v) {
|
||||
@@ -78,6 +80,13 @@ struct test_print<const char*> {
|
||||
strm<<'"'<<escape(v)<<'"';
|
||||
}
|
||||
};
|
||||
template<typename E>
|
||||
struct test_print<std::vector<E>, typename std::enable_if<sizeof(E)==1>::type> {
|
||||
template<class C>
|
||||
static inline void op(C& strm, const std::vector<E>& v) {
|
||||
strm<<'"'<<escape((const char*)v.data(), v.size())<<'"';
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
testCase testEq(const char *sLHS, const LHS& lhs, const char *sRHS, const RHS& rhs)
|
||||
|
||||
+11
-2
@@ -26,9 +26,11 @@ namespace detail {
|
||||
class Escaper
|
||||
{
|
||||
const char* val;
|
||||
size_t count;
|
||||
friend std::ostream& operator<<(std::ostream& strm, const Escaper& esc);
|
||||
public:
|
||||
constexpr explicit Escaper(const char* v) :val(v) {}
|
||||
PVXS_API explicit Escaper(const char* v);
|
||||
constexpr explicit Escaper(const char* v, size_t l) :val(v),count(l) {}
|
||||
};
|
||||
|
||||
PVXS_API
|
||||
@@ -42,7 +44,7 @@ std::ostream& operator<<(std::ostream& strm, const Escaper& esc);
|
||||
//! std::cout<<pvxs::escape(blah);
|
||||
//! @endcode
|
||||
inline detail::Escaper escape(const std::string& s) {
|
||||
return detail::Escaper(s.c_str());
|
||||
return detail::Escaper(s.c_str(), s.size());
|
||||
}
|
||||
//! Print string to output string with non-printable charactors escaped.
|
||||
//! @code
|
||||
@@ -51,6 +53,13 @@ inline detail::Escaper escape(const std::string& s) {
|
||||
inline detail::Escaper escape(const char* s) {
|
||||
return detail::Escaper(s);
|
||||
}
|
||||
//! Print string to output string with non-printable charactors escaped.
|
||||
//! @code
|
||||
//! std::cout<<pvxs::escape("this \"is a test\"", 6); // prints 'this \"'
|
||||
//! @endcode
|
||||
inline detail::Escaper escape(const char* s,size_t n) {
|
||||
return detail::Escaper(s,n);
|
||||
}
|
||||
|
||||
//! representation of a network address
|
||||
struct PVXS_API SockAddr {
|
||||
|
||||
+6
-1
@@ -39,13 +39,18 @@ void cleanup_for_valgrind()
|
||||
|
||||
namespace detail {
|
||||
|
||||
Escaper::Escaper(const char* v)
|
||||
:val(v)
|
||||
,count(v ? strlen(v) : 0)
|
||||
{}
|
||||
|
||||
std::ostream& operator<<(std::ostream& strm, const Escaper& esc)
|
||||
{
|
||||
const char *s = esc.val;
|
||||
if(!s) {
|
||||
strm<<"<NULL>";
|
||||
} else {
|
||||
for(; *s; s++) {
|
||||
for(size_t n=0; n<esc.count; n++,s++) {
|
||||
char c = *s, next;
|
||||
switch(c) {
|
||||
case '\a': next = 'a'; break;
|
||||
|
||||
Reference in New Issue
Block a user