Merge pull request #86 from K0n63n/master

Add comments, optimize some functions, add static asserts
This commit is contained in:
Luca Boccassi 2016-10-23 00:21:59 +01:00 committed by GitHub
commit c5611d6aff

View File

@ -45,60 +45,72 @@ private:
std::deque<message_t> m_parts; std::deque<message_t> m_parts;
public: public:
// Default constructor
multipart_t() multipart_t()
{} {}
// Construct from socket receive
multipart_t(socket_t& socket) multipart_t(socket_t& socket)
{ {
recv(socket); recv(socket);
} }
// Construct from memory block
multipart_t(const void *src, size_t size) multipart_t(const void *src, size_t size)
{ {
addmem(src, size); addmem(src, size);
} }
// Construct from string
multipart_t(const std::string& string) multipart_t(const std::string& string)
{ {
addstr(string); addstr(string);
} }
// Construct from message part
multipart_t(message_t&& message) multipart_t(message_t&& message)
{ {
add(std::move(message)); add(std::move(message));
} }
// Move constructor
multipart_t(multipart_t&& other) multipart_t(multipart_t&& other)
{ {
std::swap(m_parts, other.m_parts); m_parts = std::move(other.m_parts);
} }
// Move assignment operator
multipart_t& operator=(multipart_t&& other) multipart_t& operator=(multipart_t&& other)
{ {
std::swap(m_parts, other.m_parts); m_parts = std::move(other.m_parts);
return *this; return *this;
} }
// Destructor
virtual ~multipart_t() virtual ~multipart_t()
{ {
clear(); clear();
} }
// Delete all parts
void clear() void clear()
{ {
m_parts.clear(); m_parts.clear();
} }
// Get number of parts
size_t size() const size_t size() const
{ {
return m_parts.size(); return m_parts.size();
} }
// Check if number of parts is zero
bool empty() const bool empty() const
{ {
return m_parts.empty(); return m_parts.empty();
} }
// Receive multipart message from socket
bool recv(socket_t& socket, int flags = 0) bool recv(socket_t& socket, int flags = 0)
{ {
clear(); clear();
@ -114,6 +126,7 @@ public:
return true; return true;
} }
// Send multipart message to socket
bool send(socket_t& socket, int flags = 0) bool send(socket_t& socket, int flags = 0)
{ {
flags &= ~(ZMQ_SNDMORE); flags &= ~(ZMQ_SNDMORE);
@ -129,104 +142,115 @@ public:
return true; return true;
} }
// Concatenate other multipart to front
void prepend(multipart_t&& other) void prepend(multipart_t&& other)
{ {
while (!other.empty()) while (!other.empty())
push(other.remove()); push(other.remove());
} }
// Concatenate other multipart to back
void append(multipart_t&& other) void append(multipart_t&& other)
{ {
while (!other.empty()) while (!other.empty())
add(other.pop()); add(other.pop());
} }
// Push memory block to front
void pushmem(const void *src, size_t size) void pushmem(const void *src, size_t size)
{ {
m_parts.push_front(message_t(src, size)); m_parts.push_front(message_t(src, size));
} }
// Push memory block to back
void addmem(const void *src, size_t size) void addmem(const void *src, size_t size)
{ {
m_parts.push_back(message_t(src, size)); m_parts.push_back(message_t(src, size));
} }
// Push string to front
void pushstr(const std::string& string) void pushstr(const std::string& string)
{ {
m_parts.push_front(message_t(string.data(), string.size())); m_parts.push_front(message_t(string.data(), string.size()));
} }
// Push string to back
void addstr(const std::string& string) void addstr(const std::string& string)
{ {
m_parts.push_back(message_t(string.data(), string.size())); m_parts.push_back(message_t(string.data(), string.size()));
} }
// Push type (fixed-size) to front
template<typename T> template<typename T>
void pushtyp(const T& type) void pushtyp(const T& type)
{ {
static_assert(!std::is_same<T, std::string>::value, "Use pushstr() instead of pushtyp<std::string>()");
m_parts.push_front(message_t(&type, sizeof(type))); m_parts.push_front(message_t(&type, sizeof(type)));
} }
// Push type (fixed-size) to back
template<typename T> template<typename T>
void addtyp(const T& type) void addtyp(const T& type)
{ {
static_assert(!std::is_same<T, std::string>::value, "Use addstr() instead of addtyp<std::string>()");
m_parts.push_back(message_t(&type, sizeof(type))); m_parts.push_back(message_t(&type, sizeof(type)));
} }
// Push message part to front
void push(message_t&& message) void push(message_t&& message)
{ {
m_parts.push_front(std::move(message)); m_parts.push_front(std::move(message));
} }
// Push message part to back
void add(message_t&& message) void add(message_t&& message)
{ {
m_parts.push_back(std::move(message)); m_parts.push_back(std::move(message));
} }
// Pop string from front
std::string popstr() std::string popstr()
{ {
if (m_parts.empty())
return "";
std::string string(m_parts.front().data<char>(), m_parts.front().size()); std::string string(m_parts.front().data<char>(), m_parts.front().size());
m_parts.pop_front(); m_parts.pop_front();
return string; return string;
} }
// Pop type (fixed-size) from front
template<typename T> template<typename T>
T poptyp() T poptyp()
{ {
if (m_parts.empty()) static_assert(!std::is_same<T, std::string>::value, "Use popstr() instead of poptyp<std::string>()");
return T(); if (sizeof(T) != m_parts.front().size())
throw std::exception("Invalid type, size does not match the message size");
T type = *m_parts.front().data<T>(); T type = *m_parts.front().data<T>();
m_parts.pop_front(); m_parts.pop_front();
return type; return type;
} }
// Pop message part from front
message_t pop() message_t pop()
{ {
if (m_parts.empty())
return message_t(0);
message_t message = std::move(m_parts.front()); message_t message = std::move(m_parts.front());
m_parts.pop_front(); m_parts.pop_front();
return message; return message;
} }
// Pop message part from back
message_t remove() message_t remove()
{ {
if (m_parts.empty())
return message_t(0);
message_t message = std::move(m_parts.back()); message_t message = std::move(m_parts.back());
m_parts.pop_back(); m_parts.pop_back();
return message; return message;
} }
// Get pointer to a specific message part
const message_t* peek(size_t index) const const message_t* peek(size_t index) const
{ {
if (index >= size())
return nullptr;
return &m_parts[index]; return &m_parts[index];
} }
// Create multipart from type (fixed-size)
template<typename T> template<typename T>
static multipart_t create(const T& type) static multipart_t create(const T& type)
{ {
@ -235,6 +259,7 @@ public:
return multipart; return multipart;
} }
// Copy multipart
multipart_t clone() const multipart_t clone() const
{ {
multipart_t multipart; multipart_t multipart;
@ -243,6 +268,7 @@ public:
return multipart; return multipart;
} }
// Dump content to string
std::string str() const std::string str() const
{ {
std::stringstream ss; std::stringstream ss;
@ -278,6 +304,7 @@ public:
return ss.str(); return ss.str();
} }
// Check if equal to other multipart
bool equal(const multipart_t* other) const bool equal(const multipart_t* other) const
{ {
if (size() != other->size()) if (size() != other->size())
@ -288,6 +315,7 @@ public:
return true; return true;
} }
// Self test
static int test() static int test()
{ {
bool ok = true; bool ok = true;