@@ -45,60 +45,72 @@ class multipart_t
4545 std::deque<message_t > m_parts;
4646
4747public:
48+ // Default constructor
4849 multipart_t ()
4950 {}
5051
52+ // Construct from socket receive
5153 multipart_t (socket_t & socket)
5254 {
5355 recv (socket);
5456 }
5557
58+ // Construct from memory block
5659 multipart_t (const void *src, size_t size)
5760 {
5861 addmem (src, size);
5962 }
6063
64+ // Construct from string
6165 multipart_t (const std::string& string)
6266 {
6367 addstr (string);
6468 }
6569
70+ // Construct from message part
6671 multipart_t (message_t && message)
6772 {
6873 add (std::move (message));
6974 }
7075
76+ // Move constructor
7177 multipart_t (multipart_t && other)
7278 {
73- std::swap (m_parts, other.m_parts );
79+ m_parts = std::move ( other.m_parts );
7480 }
7581
82+ // Move assignment operator
7683 multipart_t & operator =(multipart_t && other)
7784 {
78- std::swap (m_parts, other.m_parts );
85+ m_parts = std::move ( other.m_parts );
7986 return *this ;
8087 }
8188
89+ // Destructor
8290 virtual ~multipart_t ()
8391 {
8492 clear ();
8593 }
8694
95+ // Delete all parts
8796 void clear ()
8897 {
8998 m_parts.clear ();
9099 }
91100
101+ // Get number of parts
92102 size_t size () const
93103 {
94104 return m_parts.size ();
95105 }
96106
107+ // Check if number of parts is zero
97108 bool empty () const
98109 {
99110 return m_parts.empty ();
100111 }
101112
113+ // Receive multipart message from socket
102114 bool recv (socket_t & socket, int flags = 0 )
103115 {
104116 clear ();
@@ -114,6 +126,7 @@ class multipart_t
114126 return true ;
115127 }
116128
129+ // Send multipart message to socket
117130 bool send (socket_t & socket, int flags = 0 )
118131 {
119132 flags &= ~(ZMQ_SNDMORE);
@@ -129,104 +142,115 @@ class multipart_t
129142 return true ;
130143 }
131144
145+ // Concatenate other multipart to front
132146 void prepend (multipart_t && other)
133147 {
134148 while (!other.empty ())
135149 push (other.remove ());
136150 }
137151
152+ // Concatenate other multipart to back
138153 void append (multipart_t && other)
139154 {
140155 while (!other.empty ())
141156 add (other.pop ());
142157 }
143158
159+ // Push memory block to front
144160 void pushmem (const void *src, size_t size)
145161 {
146162 m_parts.push_front (message_t (src, size));
147163 }
148164
165+ // Push memory block to back
149166 void addmem (const void *src, size_t size)
150167 {
151168 m_parts.push_back (message_t (src, size));
152169 }
153170
171+ // Push string to front
154172 void pushstr (const std::string& string)
155173 {
156174 m_parts.push_front (message_t (string.data (), string.size ()));
157175 }
158176
177+ // Push string to back
159178 void addstr (const std::string& string)
160179 {
161180 m_parts.push_back (message_t (string.data (), string.size ()));
162181 }
163182
183+ // Push type (fixed-size) to front
164184 template <typename T>
165185 void pushtyp (const T& type)
166186 {
187+ static_assert (!std::is_same<T, std::string>::value, " Use pushstr() instead of pushtyp<std::string>()" );
167188 m_parts.push_front (message_t (&type, sizeof (type)));
168189 }
169190
191+ // Push type (fixed-size) to back
170192 template <typename T>
171193 void addtyp (const T& type)
172194 {
195+ static_assert (!std::is_same<T, std::string>::value, " Use addstr() instead of addtyp<std::string>()" );
173196 m_parts.push_back (message_t (&type, sizeof (type)));
174197 }
175198
199+ // Push message part to front
176200 void push (message_t && message)
177201 {
178202 m_parts.push_front (std::move (message));
179203 }
180204
205+ // Push message part to back
181206 void add (message_t && message)
182207 {
183208 m_parts.push_back (std::move (message));
184209 }
185210
211+ // Pop string from front
186212 std::string popstr ()
187213 {
188- if (m_parts.empty ())
189- return " " ;
190214 std::string string (m_parts.front ().data <char >(), m_parts.front ().size ());
191215 m_parts.pop_front ();
192216 return string;
193217 }
194218
219+ // Pop type (fixed-size) from front
195220 template <typename T>
196221 T poptyp ()
197222 {
198- if (m_parts.empty ())
199- return T ();
223+ static_assert (!std::is_same<T, std::string>::value, " Use popstr() instead of poptyp<std::string>()" );
224+ if (sizeof (T) != m_parts.front ().size ())
225+ throw std::exception (" Invalid type, size does not match the message size" );
200226 T type = *m_parts.front ().data <T>();
201227 m_parts.pop_front ();
202228 return type;
203229 }
204230
231+ // Pop message part from front
205232 message_t pop ()
206233 {
207- if (m_parts.empty ())
208- return message_t (0 );
209234 message_t message = std::move (m_parts.front ());
210235 m_parts.pop_front ();
211236 return message;
212237 }
213238
239+ // Pop message part from back
214240 message_t remove ()
215241 {
216- if (m_parts.empty ())
217- return message_t (0 );
218242 message_t message = std::move (m_parts.back ());
219243 m_parts.pop_back ();
220244 return message;
221245 }
222246
247+ // Get pointer to a specific message part
223248 const message_t * peek (size_t index) const
224249 {
225- if (index >= size ())
226- return nullptr ;
227250 return &m_parts[index];
228251 }
229252
253+ // Create multipart from type (fixed-size)
230254 template <typename T>
231255 static multipart_t create (const T& type)
232256 {
@@ -235,6 +259,7 @@ class multipart_t
235259 return multipart;
236260 }
237261
262+ // Copy multipart
238263 multipart_t clone () const
239264 {
240265 multipart_t multipart;
@@ -243,6 +268,7 @@ class multipart_t
243268 return multipart;
244269 }
245270
271+ // Dump content to string
246272 std::string str () const
247273 {
248274 std::stringstream ss;
@@ -278,6 +304,7 @@ class multipart_t
278304 return ss.str ();
279305 }
280306
307+ // Check if equal to other multipart
281308 bool equal (const multipart_t * other) const
282309 {
283310 if (size () != other->size ())
@@ -288,6 +315,7 @@ class multipart_t
288315 return true ;
289316 }
290317
318+ // Self test
291319 static int test ()
292320 {
293321 bool ok = true ;
0 commit comments