]> git.meshlink.io Git - meshlink/blob - src/packmsg.h
When activating a meta-connection, remember the address of the peer.
[meshlink] / src / packmsg.h
1 #pragma once
2
3 /*
4     SPDX-License-Identifier: BSD-3-Clause
5
6     packmsg.h -- Little-endian MessagePack implementation, optimized for speed
7     Copyright (C) 2018 Guus Sliepen <guus@tinc-vpn.org>
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions
11     are met:
12     1. Redistributions of source code must retain the above copyright
13        notice, this list of conditions and the following disclaimer.
14     2. Redistributions in binary form must reproduce the above copyright
15        notice, this list of conditions and the following disclaimer in the
16        documentation and/or other materials provided with the distribution.
17     3. Neither the name of the University nor the names of its contributors
18        may be used to endorse or promote products derived from this software
19        without specific prior written permission.
20
21     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
22     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24     ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31     DAMAGE.
32 */
33
34 #include <stdint.h>
35 #include <stdbool.h>
36 #include <stdlib.h>
37 #include <stddef.h>
38 #include <string.h>
39 #include <assert.h>
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 #define packmsg_likely(x) __builtin_expect(!!(x), 1)
46 #define packmsg_unlikely(x) __builtin_expect(!!(x), 0)
47
48 /** \mainpage PackMessage, a safe and fast header-only C library for little-endian MessagePack encoding and decoding.
49  *
50  * This library can encode and decode MessagePack objects, however it differs in one important point
51  * from the official MessagePack specification: PackMessage stores all values in little-endian format.
52  * PackMessage offers a simple streaming API for encoding and decoding.
53  *
54  * PackMessage is *safe*:
55  *
56  * * Reads from and writes to buffers are always bounds checked.
57  * * String, binary and extension data can be read into buffers allocated by PackMessage using simple API calls.
58  * * Any error will result in null values and pointers being returned, and/or application-allocated buffers for strings will be zero-terminated, so there is no undefined state.
59  * * Once an encoding/decoding error occurs, all subsequent operations on the same buffer will also fail.
60  * * The API is designed to follow the principle of least surprise, and makes it hard to use in a wrong way.
61  *
62  * PackMessage is *fast*:
63  *
64  * * Values are stored in little-endian format, since virtually all mainstream processors are little-endian, or they can switch between endianness and are probably running an operating system that has configured it to be little-endian. This saves the overhead of converting to and from big-endian format.
65  * * No memory allocation is done unless requested.
66  * * The application can get const pointers to string, binary and extension data pointing into the input buffer if desired, avoiding copies.
67  * * The application does not have to check for errors after for every operation; it can be done once after encoding/decoding a buffer if desired.
68  * * The library is header-only, allowing the compiler to inline all functions and better optimize your application.
69  *
70  * ## API overview
71  *
72  * For encoding, a packmsg_output_t variable must be initialized
73  * with a pointer to the start of an output buffer, and its size.
74  * Elements can then be encoded using packmsg_add_*() functions.
75  * When all desired elements have been added, the length of the encoded message
76  * can be retrieved using the packmsg_output_size() function.
77  *
78  * For decoding, a packmsg_input_t variable must be initialized
79  * with a const pointer to the start of an input buffer, and its size.
80  * Elements can then be decoded using packmsg_get_*() functions.
81  * If the type of elements in a message is not known up front, then
82  * the type of the next element can be queried using packmsg_get_type()
83  * or packmsg_is_*() functions. To check that the complete message has been decoded
84  * correctly, the function packmsg_done() can be called.
85  *
86  * ## Example code
87  *
88  * @ref example.c
89  *
90  * \example example.c
91  *
92  * This is an example of how to encode and decode the equivalent of the JSON object `{"compact": true, "schema": 0}`
93  * using PackMessage.
94  */
95
96 /* Buffer iterators
97  * ================
98  */
99
100 /** \brief Iterator for PackMessage output.
101  *
102  * This is an iterator that has to be initialized with a pointer to
103  * an output buffer that is allocated by the application,
104  * and the length of that buffer. A pointer to it is passed to all
105  * packmsg_add_*() functions.
106  */
107 typedef struct packmsg_output {
108         uint8_t *ptr;  /**< A pointer into a buffer. */
109         ptrdiff_t len; /**< The remaining length of the buffer, or -1 in case of errors. */
110 } packmsg_output_t;
111
112 /** \brief Iterator for PackMessage input.
113  *
114  * This is an iterator that has to be initialized with a pointer to
115  * an input buffer that is allocated by the application,
116  * and the length of that buffer. A pointer to it is passed to all
117  * packmsg_get_*() functions.
118  */
119 typedef struct packmsg_input {
120         const uint8_t *ptr; /**< A pointer into a buffer. */
121         ptrdiff_t len;      /**< The remaining length of the buffer, or -1 in case of errors. */
122 } packmsg_input_t;
123
124 /* Checks
125  * ======
126  */
127
128 /** \brief Check if the PackMessage output buffer is in a valid state.
129  *  \memberof packmsg_output
130  *
131  * This function checks if all operations performed on the output buffer so far
132  * have all completed successfully, and the buffer contains a valid PackMessage message.
133  *
134  * \param buf  A pointer to an output buffer iterator.
135  *
136  * \return     True if all write operations performed on the output buffer so far have completed successfully,
137  *             false if any error has occurred.
138  */
139 static inline bool packmsg_output_ok(const packmsg_output_t *buf) {
140         assert(buf);
141
142         return packmsg_likely(buf->len >= 0);
143 }
144
145 /** \brief Calculate the amount of bytes written to the output buffer.
146  *  \memberof packmsg_output
147  *
148  * This function calculates the amount of bytes written to the output buffer
149  * based on the current position of the output iterator, and a pointer to the start of the buffer.
150  *
151  * \param buf    A pointer to an output buffer iterator.
152  * \param start  A pointer to the start of the output buffer.
153  *
154  * \return       The total amount of bytes written to the output buffer,
155  *               or 0 if any error has occurred.
156  */
157 static inline size_t packmsg_output_size(const packmsg_output_t *buf, const uint8_t *start) {
158         if(packmsg_likely(packmsg_output_ok(buf))) {
159                 return buf->ptr - start;
160         } else {
161                 return 0;
162         }
163 }
164
165 /** \brief Check if the PackMessage input buffer is in a valid state.
166  *  \memberof packmsg_input
167  *
168  * This function checks if all operations performed on the input buffer so far
169  * have all completed successfully, and the buffer contains a valid PackMessage message.
170  *
171  * \param buf  A pointer to an input buffer iterator.
172  *
173  * \return     True if all read operations performed on the input buffer so far have completed successfully,
174  *             false if any error has occurred.
175  */
176 static inline __attribute__((__warn_unused_result__)) bool packmsg_input_ok(const packmsg_input_t *buf) {
177         assert(buf);
178
179         return packmsg_likely(buf->len >= 0);
180 }
181
182 /** \brief Check if the PackMessage input buffer has been read completely.
183  *  \memberof packmsg_input
184  *
185  * This function checks if all data in the input buffer has been consumed
186  * by input operations. This function should always be called after the last
187  * input operation, when one expects the whole buffer to have been read.
188  *
189  * \param buf  A pointer to an input buffer iterator.
190  *
191  * \return     True if the whole input buffer has been read successfully,
192  *             false if there is still data remaining in the input buffer,
193  *             or if any error has occurred.
194  */
195 static inline __attribute__((__warn_unused_result__)) bool packmsg_done(const packmsg_input_t *buf) {
196         assert(buf);
197
198         return buf->len == 0;
199 }
200
201 /* Invalidation functions
202  * ======================
203  */
204
205 /** \brief Invalidate an output iterator.
206  *  \memberof packmsg_output
207  *
208  * This function invalidates an output iterator. This signals that an error occurred,
209  * and prevents further output to be written.
210  *
211  * \param buf  A pointer to an output buffer iterator.
212  */
213 static inline void packmsg_output_invalidate(packmsg_output_t *buf) {
214         buf->len = -1;
215 }
216
217 /** \brief Invalidate an input iterator.
218  *  \memberof packmsg_input
219  *
220  * This function invalidates an input iterator. This signals that an error occurred,
221  * and prevents further input to be read.
222  *
223  * \param buf  A pointer to an input buffer iterator.
224  */
225 static inline void packmsg_input_invalidate(packmsg_input_t *buf) {
226         buf->len = -1;
227 }
228
229 /* Encoding functions
230  * ==================
231  */
232
233 /** \brief Internal function, do not use. */
234 static inline void packmsg_write_hdr_(packmsg_output_t *buf, uint8_t hdr) {
235         assert(buf);
236         assert(buf->ptr);
237
238         if(packmsg_likely(buf->len > 0)) {
239                 *buf->ptr = hdr;
240                 buf->ptr++;
241                 buf->len--;
242         } else {
243                 packmsg_output_invalidate(buf);
244         }
245 }
246
247 /** \brief Internal function, do not use. */
248 static inline void packmsg_write_data_(packmsg_output_t *buf, const void *data, uint32_t dlen) {
249         assert(buf);
250         assert(buf->ptr);
251         assert(data);
252
253         if(packmsg_likely(buf->len >= dlen)) {
254                 memcpy(buf->ptr, data, dlen);
255                 buf->ptr += dlen;
256                 buf->len -= dlen;
257         } else {
258                 packmsg_output_invalidate(buf);
259         }
260 }
261
262 /** \brief Internal function, do not use. */
263 static inline void packmsg_write_hdrdata_(packmsg_output_t *buf, uint8_t hdr, const void *data, uint32_t dlen) {
264         assert(buf);
265         assert(buf->ptr);
266         assert(data);
267
268         if(packmsg_likely(buf->len > dlen)) {
269                 *buf->ptr = hdr;
270                 buf->ptr++;
271                 buf->len--;
272
273                 memcpy(buf->ptr, data, dlen);
274                 buf->ptr += dlen;
275                 buf->len -= dlen;
276         } else {
277                 packmsg_output_invalidate(buf);
278         }
279 }
280
281 /** \brief Internal function, do not use. */
282 static inline void *packmsg_reserve_(packmsg_output_t *buf, uint32_t len) {
283         assert(buf);
284         assert(buf->ptr);
285
286         if(packmsg_likely(buf->len >= len)) {
287                 void *ptr = buf->ptr;
288                 buf->ptr += len;
289                 buf->len -= len;
290                 return ptr;
291         } else {
292                 packmsg_output_invalidate(buf);
293                 return NULL;
294         }
295 }
296
297 /** \brief Add a NIL to the output.
298  *  \memberof packmsg_output
299  *
300  * \param buf  A pointer to an output buffer iterator.
301  */
302 static inline void packmsg_add_nil(packmsg_output_t *buf) {
303         packmsg_write_hdr_(buf, 0xc0);
304 }
305
306 /** \brief Add a boolean value to the output.
307  *  \memberof packmsg_output
308  *
309  * \param buf  A pointer to an output buffer iterator.
310  * \param val  The value to add.
311  */
312 static inline void packmsg_add_bool(packmsg_output_t *buf, bool val) {
313         packmsg_write_hdr_(buf, val ? 0xc3 : 0xc2);
314 }
315
316 /** \brief Add an int8 value to the output.
317  *  \memberof packmsg_output
318  *
319  * \param buf  A pointer to an output buffer iterator.
320  * \param val  The value to add.
321  */
322 static inline void packmsg_add_int8(packmsg_output_t *buf, int8_t val) {
323         if(val >= -32) {        // fixint
324                 packmsg_write_hdr_(buf, val);
325         } else {                // TODO: negative fixint
326                 packmsg_write_hdrdata_(buf, 0xd0, &val, 1);
327         }
328 }
329
330 /** \brief Add an int16 value to the output.
331  *  \memberof packmsg_output
332  *
333  * \param buf  A pointer to an output buffer iterator.
334  * \param val  The value to add.
335  */
336 static inline void packmsg_add_int16(packmsg_output_t *buf, int16_t val) {
337         if((int8_t) val != val) {
338                 packmsg_write_hdrdata_(buf, 0xd1, &val, 2);
339         } else {
340                 packmsg_add_int8(buf, val);
341         }
342 }
343
344 /** \brief Add an int32 value to the output.
345  *  \memberof packmsg_output
346  *
347  * \param buf  A pointer to an output buffer iterator.
348  * \param val  The value to add.
349  */
350 static inline void packmsg_add_int32(packmsg_output_t *buf, int32_t val) {
351         if((int16_t) val != val) {
352                 packmsg_write_hdrdata_(buf, 0xd2, &val, 4);
353         } else {
354                 packmsg_add_int16(buf, val);
355         }
356 }
357
358 /** \brief Add an int64 value to the output.
359  *  \memberof packmsg_output
360  *
361  * \param buf  A pointer to an output buffer iterator.
362  * \param val  The value to add.
363  */
364 static inline void packmsg_add_int64(packmsg_output_t *buf, int64_t val) {
365         if((int32_t) val != val) {
366                 packmsg_write_hdrdata_(buf, 0xd3, &val, 8);
367         } else {
368                 packmsg_add_int32(buf, val);
369         }
370 }
371
372 /** \brief Add a uint8 value to the output.
373  *  \memberof packmsg_output
374  *
375  * \param buf  A pointer to an output buffer iterator.
376  * \param val  The value to add.
377  */
378 static inline void packmsg_add_uint8(packmsg_output_t *buf, uint8_t val) {
379         if(val < 0x80) {        // fixint
380                 packmsg_write_hdr_(buf, val);
381         } else {
382                 packmsg_write_hdrdata_(buf, 0xcc, &val, 1);
383         }
384 }
385
386 /** \brief Add a uint16 value to the output.
387  *  \memberof packmsg_output
388  *
389  * \param buf  A pointer to an output buffer iterator.
390  * \param val  The value to add.
391  */
392 static inline void packmsg_add_uint16(packmsg_output_t *buf, uint16_t val) {
393         if(val & 0xff00) {
394                 packmsg_write_hdrdata_(buf, 0xcd, &val, 2);
395         } else {
396                 packmsg_add_uint8(buf, val);
397         }
398 }
399
400 /** \brief Add a int32 value to the output.
401  *  \memberof packmsg_output
402  *
403  * \param buf  A pointer to an output buffer iterator.
404  * \param val  The value to add.
405  */
406 static inline void packmsg_add_uint32(packmsg_output_t *buf, uint32_t val) {
407         if(val & 0xffff0000) {
408                 packmsg_write_hdrdata_(buf, 0xce, &val, 4);
409         } else {
410                 packmsg_add_uint16(buf, val);
411         }
412 }
413
414 /** \brief Add a int64 value to the output.
415  *  \memberof packmsg_output
416  *
417  * \param buf  A pointer to an output buffer iterator.
418  * \param val  The value to add.
419  */
420 static inline void packmsg_add_uint64(packmsg_output_t *buf, uint64_t val) {
421         if(val & 0xffffffff00000000) {
422                 packmsg_write_hdrdata_(buf, 0xcf, &val, 8);
423         } else {
424                 packmsg_add_uint32(buf, val);
425         }
426 }
427
428 /** \brief Add a float value to the output.
429  *  \memberof packmsg_output
430  *
431  * \param buf  A pointer to an output buffer iterator.
432  * \param val  The value to add.
433  */
434 static inline void packmsg_add_float(packmsg_output_t *buf, float val) {
435         packmsg_write_hdrdata_(buf, 0xca, &val, 4);
436 }
437
438 /** \brief Add a double value to the output.
439  *  \memberof packmsg_output
440  *
441  * \param buf  A pointer to an output buffer iterator.
442  * \param val  The value to add.
443  */
444 static inline void packmsg_add_double(packmsg_output_t *buf, double val) {
445         packmsg_write_hdrdata_(buf, 0xcb, &val, 8);
446 }
447
448 /** \brief Add a string with a given length to the output.
449  *  \memberof packmsg_output
450  *
451  * The string must be at least as long as the given length.
452  * Any NUL-bytes within the given length range will be included.
453  *
454  * \param buf  A pointer to an output buffer iterator.
455  * \param str  The string to add.
456  * \param len  The length of the string in bytes.
457  */
458 static inline void packmsg_add_str_raw(packmsg_output_t *buf, const char *str, uint32_t len) {
459         if(len < 32) {
460                 packmsg_write_hdr_(buf, 0xa0 | (uint8_t) len);
461         } else if(len <= 0xff) {
462                 packmsg_write_hdrdata_(buf, 0xd9, &len, 1);
463         } else if(len <= 0xffff) {
464                 packmsg_write_hdrdata_(buf, 0xda, &len, 2);
465         } else {
466                 packmsg_write_hdrdata_(buf, 0xdb, &len, 4);
467         }
468
469         packmsg_write_data_(buf, str, len);
470 }
471
472 /** \brief Add a string to the output.
473  *  \memberof packmsg_output
474  *
475  * \param buf  A pointer to an output buffer iterator.
476  * \param str  The string to add. This must be a NUL-terminated string.
477  */
478 static inline void packmsg_add_str(packmsg_output_t *buf, const char *str) {
479         size_t len = strlen(str);
480
481         if(packmsg_likely(len <= 0xffffffff)) {
482                 packmsg_add_str_raw(buf, str, len);
483         } else {
484                 packmsg_output_invalidate(buf);
485         }
486 }
487
488 /** \brief Reserve space for a string with a given length in the output.
489  *  \memberof packmsg_output
490  *
491  * This writes a header for a string with the given length to the output,
492  * and reserves space for that string.
493  * The caller must fill in that space.
494  *
495  * \param buf  A pointer to an output buffer iterator.
496  * \param len  The length of the string in bytes.
497  *
498  * \return     A pointer to the reserved space for the string,
499  *             or NULL in case of an error.
500  */
501 static inline char *packmsg_add_str_reserve(packmsg_output_t *buf, uint32_t len) {
502         if(len < 32) {
503                 packmsg_write_hdr_(buf, 0xa0 | (uint8_t) len);
504         } else if(len <= 0xff) {
505                 packmsg_write_hdrdata_(buf, 0xd9, &len, 1);
506         } else if(len <= 0xffff) {
507                 packmsg_write_hdrdata_(buf, 0xda, &len, 2);
508         } else {
509                 packmsg_write_hdrdata_(buf, 0xdb, &len, 4);
510         }
511
512         return (char *)packmsg_reserve_(buf, len);
513 }
514
515 /** \brief Add binary data to the output.
516  *  \memberof packmsg_output
517  *
518  * \param buf   A pointer to an output buffer iterator.
519  * \param data  A pointer to the data to add.
520  * \param dlen  The length of the data in bytes.
521  */
522 static inline void packmsg_add_bin(packmsg_output_t *buf, const void *data, uint32_t dlen) {
523         if(dlen <= 0xff) {
524                 packmsg_write_hdrdata_(buf, 0xc4, &dlen, 1);
525         } else if(dlen <= 0xffff) {
526                 packmsg_write_hdrdata_(buf, 0xc5, &dlen, 2);
527         } else {
528                 packmsg_write_hdrdata_(buf, 0xc6, &dlen, 4);
529         }
530
531         packmsg_write_data_(buf, data, dlen);
532 }
533
534 /** \brief Reserve space for binary data in the output.
535  *  \memberof packmsg_output
536  *
537  * This writes a header for a block of data with the given length to the output,
538  * and reserves space for that data.
539  * The caller must fill in that space.
540  *
541  * \param buf   A pointer to an output buffer iterator.
542  * \param dlen  The length of the data in bytes.
543  *
544  * \return      A pointer to the reserved space for the data,
545  *              or NULL in case of an error.
546  */
547 static inline void *packmsg_add_bin_reserve(packmsg_output_t *buf, uint32_t dlen) {
548         if(dlen <= 0xff) {
549                 packmsg_write_hdrdata_(buf, 0xc4, &dlen, 1);
550         } else if(dlen <= 0xffff) {
551                 packmsg_write_hdrdata_(buf, 0xc5, &dlen, 2);
552         } else {
553                 packmsg_write_hdrdata_(buf, 0xc6, &dlen, 4);
554         }
555
556         return packmsg_reserve_(buf, dlen);
557 }
558
559 /** \brief Add extension data to the output.
560  *  \memberof packmsg_output
561  *
562  * \param buf   A pointer to an output buffer iterator.
563  * \param type  The extension type. Values between 0 and 127 are application specific,
564  *              values between -1 and -128 are reserved for future extensions.
565  * \param data  A pointer to the data to add.
566  * \param dlen  The length of the data in bytes.
567  */
568 static inline void packmsg_add_ext(packmsg_output_t *buf, int8_t type, const void *data, uint32_t dlen) {
569         if(dlen <= 0xff) {
570                 if(dlen == 16) {
571                         packmsg_write_hdrdata_(buf, 0xd8, &type, 1);
572                 } else if(dlen == 8) {
573                         packmsg_write_hdrdata_(buf, 0xd7, &type, 1);
574                 } else if(dlen == 4) {
575                         packmsg_write_hdrdata_(buf, 0xd6, &type, 1);
576                 } else if(dlen == 2) {
577                         packmsg_write_hdrdata_(buf, 0xd5, &type, 1);
578                 } else if(dlen == 1) {
579                         packmsg_write_hdrdata_(buf, 0xd4, &type, 1);
580                 } else {
581                         packmsg_write_hdrdata_(buf, 0xc7, &dlen, 1);
582                         packmsg_write_data_(buf, &type, 1);
583                 }
584         } else if(dlen <= 0xffff) {
585                 packmsg_write_hdrdata_(buf, 0xc8, &dlen, 2);
586                 packmsg_write_data_(buf, &type, 1);
587         } else if(dlen <= 0xffffffff) {
588                 packmsg_write_hdrdata_(buf, 0xc9, &dlen, 4);
589                 packmsg_write_data_(buf, &type, 1);
590         } else {
591                 packmsg_output_invalidate(buf);
592                 return;
593         }
594
595         packmsg_write_data_(buf, data, dlen);
596 }
597
598 /** \brief Reserve space for extension data in the output.
599  *  \memberof packmsg_output
600  *
601  * This writes a header for extension data with the given type
602  * and length to the output,
603  * and reserves space for that extension data.
604  * The caller must fill in that space.
605  *
606  * \param buf   A pointer to an output buffer iterator.
607  * \param type  The extension type. Values between 0 and 127 are application specific,
608  *              values between -1 and -128 are reserved for future extensions.
609  * \param dlen  The length of the data in bytes.
610  *
611  * \return      A pointer to the reserved space for the extension data,
612  *              or NULL in case of an error.
613  */
614 static inline void *packmsg_add_ext_reserve(packmsg_output_t *buf, int8_t type, uint32_t dlen) {
615         if(dlen <= 0xff) {
616                 if(dlen == 16) {
617                         packmsg_write_hdrdata_(buf, 0xd8, &type, 1);
618                 } else if(dlen == 8) {
619                         packmsg_write_hdrdata_(buf, 0xd7, &type, 1);
620                 } else if(dlen == 4) {
621                         packmsg_write_hdrdata_(buf, 0xd6, &type, 1);
622                 } else if(dlen == 2) {
623                         packmsg_write_hdrdata_(buf, 0xd5, &type, 1);
624                 } else if(dlen == 1) {
625                         packmsg_write_hdrdata_(buf, 0xd4, &type, 1);
626                 } else {
627                         packmsg_write_hdrdata_(buf, 0xc7, &dlen, 1);
628                         packmsg_write_data_(buf, &type, 1);
629                 }
630         } else if(dlen <= 0xffff) {
631                 packmsg_write_hdrdata_(buf, 0xc8, &dlen, 2);
632                 packmsg_write_data_(buf, &type, 1);
633         } else  {
634                 packmsg_write_hdrdata_(buf, 0xc9, &dlen, 4);
635                 packmsg_write_data_(buf, &type, 1);
636         }
637
638         return packmsg_reserve_(buf, dlen);
639 }
640
641 /** \brief Add a map header to the output.
642  *  \memberof packmsg_output
643  *
644  * This function only adds an an indicator that the next 2 * count elements
645  * are a sequence of key-value pairs that make up the contents of the map.
646  * These key-value pairs have to be added by the application using regular
647  * packmsg_add_*() calls.
648  *
649  * \param buf    A pointer to an output buffer iterator.
650  * \param count  The number of elements in the map.
651  */
652 static inline void packmsg_add_map(packmsg_output_t *buf, uint32_t count) {
653         if(count <= 0xf) {
654                 packmsg_write_hdr_(buf, 0x80 | (uint8_t) count);
655         } else if(count <= 0xffff) {
656                 packmsg_write_hdrdata_(buf, 0xde, &count, 2);
657         } else {
658                 packmsg_write_hdrdata_(buf, 0xdf, &count, 4);
659         }
660 }
661
662 /** \brief Add an array header to the output.
663  *  \memberof packmsg_output
664  *
665  * This function only adds an an indicator that the next count elements
666  * are a sequence of elements that make up the contents of the array.
667  * These elements have to be added by the application using regular
668  * packmsg_add_*() calls.
669  *
670  * \param buf    A pointer to an output buffer iterator.
671  * \param count  The number of elements in the array.
672  */
673 static inline void packmsg_add_array(packmsg_output_t *buf, uint32_t count) {
674         if(count <= 0xf) {
675                 packmsg_write_hdr_(buf, 0x90 | (uint8_t) count);
676         } else if(count <= 0xffff) {
677                 packmsg_write_hdrdata_(buf, 0xdc, &count, 2);
678         } else {
679                 packmsg_write_hdrdata_(buf, 0xdd, &count, 4);
680         }
681 }
682
683 /* Decoding functions
684  * ==================
685  */
686
687 /** \brief Internal function, do not use. */
688 static inline uint8_t packmsg_read_hdr_(packmsg_input_t *buf) {
689         assert(buf);
690         assert(buf->ptr);
691
692         if(packmsg_likely(buf->len > 0)) {
693                 uint8_t hdr = *buf->ptr;
694                 buf->ptr++;
695                 buf->len--;
696                 return hdr;
697         } else {
698                 packmsg_input_invalidate(buf);
699                 return 0xc1;
700         }
701 }
702
703 /** \brief Internal function, do not use. */
704 static inline void packmsg_read_data_(packmsg_input_t *buf, void *data, uint32_t dlen) {
705         assert(buf);
706         assert(buf->ptr);
707         assert(data);
708
709         if(packmsg_likely(buf->len >= dlen)) {
710                 memcpy(data, buf->ptr, dlen);
711                 buf->ptr += dlen;
712                 buf->len -= dlen;
713         } else {
714                 packmsg_input_invalidate(buf);
715         }
716 }
717
718 /** \brief Internal function, do not use. */
719 static inline uint8_t packmsg_peek_hdr_(const packmsg_input_t *buf) {
720         assert(buf);
721         assert(buf->ptr);
722
723         if(packmsg_likely(buf->len > 0)) {
724                 return *buf->ptr;
725         } else {
726                 return 0xc1;
727         }
728 }
729
730 /** \brief Get a NIL from the input.
731  *  \memberof packmsg_input
732  *
733  * This function does not return anything, but will invalidate the input iterator
734  * if no NIL was successfully consumed from the input.
735  *
736  * \param buf  A pointer to an input buffer iterator.
737  */
738 static inline void packmsg_get_nil(packmsg_input_t *buf) {
739         if(packmsg_read_hdr_(buf) != 0xc0) {
740                 packmsg_input_invalidate(buf);
741         }
742 }
743
744
745 /** \brief Get a boolean value from the input.
746  *  \memberof packmsg_input
747  *
748  * \param buf  A pointer to an input buffer iterator.
749  * \return     The boolean value that was read from the input,
750  *             or false in case of an error.
751  */
752 static inline bool packmsg_get_bool(packmsg_input_t *buf) {
753         uint8_t hdr = packmsg_read_hdr_(buf);
754
755         if(hdr == 0xc2) {
756                 return false;
757         } else if(hdr == 0xc3) {
758                 return true;
759         } else {
760                 packmsg_input_invalidate(buf);
761                 return false;
762         }
763 }
764
765 /** \brief Get an int8 value from the input.
766  *  \memberof packmsg_input
767  *
768  * \param buf  A pointer to an input buffer iterator.
769  * \return     The int8 value that was read from the input,
770  *             or 0 in case of an error.
771  */
772 static inline int8_t packmsg_get_int8(packmsg_input_t *buf) {
773         uint8_t hdr = packmsg_read_hdr_(buf);
774
775         if(hdr < 0x80 || hdr >= 0xe0) {
776                 return (int8_t)hdr;
777         } else if(hdr == 0xd0) {
778                 return packmsg_read_hdr_(buf);
779         } else {
780                 packmsg_input_invalidate(buf);
781                 return 0;
782         }
783 }
784
785 /** \brief Get an int16 value from the input.
786  *  \memberof packmsg_input
787  *
788  * \param buf  A pointer to an input buffer iterator.
789  * \return     The int16 value that was read from the input,
790  *             or 0 in case of an error.
791  */
792 static inline int16_t packmsg_get_int16(packmsg_input_t *buf) {
793         uint8_t hdr = packmsg_read_hdr_(buf);
794
795         if(hdr < 0x80 || hdr >= 0xe0) {
796                 return (int8_t)hdr;
797         } else if(hdr == 0xd0) {
798                 return (int8_t) packmsg_read_hdr_(buf);
799         } else if(hdr == 0xd1) {
800                 int16_t val = 0;
801                 packmsg_read_data_(buf, &val, 2);
802                 return val;
803         } else {
804                 packmsg_input_invalidate(buf);
805                 return 0;
806         }
807 }
808
809 /** \brief Get an int32 value from the input.
810  *  \memberof packmsg_input
811  *
812  * \param buf  A pointer to an input buffer iterator.
813  * \return     The int32 value that was read from the input,
814  *             or 0 in case of an error.
815  */
816 static inline int32_t packmsg_get_int32(packmsg_input_t *buf) {
817         uint8_t hdr = packmsg_read_hdr_(buf);
818
819         if(hdr < 0x80 || hdr >= 0xe0) {
820                 return (int8_t)hdr;
821         } else if(hdr == 0xd0) {
822                 return (int8_t) packmsg_read_hdr_(buf);
823         } else if(hdr == 0xd1) {
824                 int16_t val = 0;
825                 packmsg_read_data_(buf, &val, 2);
826                 return val;
827         } else if(hdr == 0xd2) {
828                 int32_t val = 0;
829                 packmsg_read_data_(buf, &val, 4);
830                 return val;
831         } else {
832                 packmsg_input_invalidate(buf);
833                 return 0;
834         }
835 }
836
837 /** \brief Get an int64 value from the input.
838  *  \memberof packmsg_input
839  *
840  * \param buf  A pointer to an input buffer iterator.
841  * \return     The int64 value that was read from the input,
842  *             or 0 in case of an error.
843  */
844 static inline int64_t packmsg_get_int64(packmsg_input_t *buf) {
845         uint8_t hdr = packmsg_read_hdr_(buf);
846
847         if(hdr < 0x80 || hdr >= 0xe0) {
848                 return (int8_t)hdr;
849         } else if(hdr == 0xd0) {
850                 return (int8_t) packmsg_read_hdr_(buf);
851         } else if(hdr == 0xd1) {
852                 int16_t val = 0;
853                 packmsg_read_data_(buf, &val, 2);
854                 return val;
855         } else if(hdr == 0xd2) {
856                 int32_t val = 0;
857                 packmsg_read_data_(buf, &val, 4);
858                 return val;
859         } else if(hdr == 0xd3) {
860                 int64_t val = 0;
861                 packmsg_read_data_(buf, &val, 8);
862                 return val;
863         } else {
864                 packmsg_input_invalidate(buf);
865                 return 0;
866         }
867 }
868
869 /** \brief Get an uint8 value from the input.
870  *  \memberof packmsg_input
871  *
872  * \param buf  A pointer to an input buffer iterator.
873  * \return     The uint8 value that was read from the input,
874  *             or 0 in case of an error.
875  */
876 static inline uint8_t packmsg_get_uint8(packmsg_input_t *buf) {
877         uint8_t hdr = packmsg_read_hdr_(buf);
878
879         if(hdr < 0x80) {
880                 return hdr;
881         } else if(hdr == 0xcc) {
882                 return packmsg_read_hdr_(buf);
883         } else {
884                 packmsg_input_invalidate(buf);
885                 return 0;
886         }
887 }
888
889 /** \brief Get an uint16 value from the input.
890  *  \memberof packmsg_input
891  *
892  * \param buf  A pointer to an input buffer iterator.
893  * \return     The uint16 value that was read from the input,
894  *             or 0 in case of an error.
895  */
896 static inline uint16_t packmsg_get_uint16(packmsg_input_t *buf) {
897         uint8_t hdr = packmsg_read_hdr_(buf);
898
899         if(hdr < 0x80) {
900                 return hdr;
901         } else if(hdr == 0xcc) {
902                 return packmsg_read_hdr_(buf);
903         } else if(hdr == 0xcd) {
904                 uint16_t val = 0;
905                 packmsg_read_data_(buf, &val, 2);
906                 return val;
907         } else {
908                 packmsg_input_invalidate(buf);
909                 return 0;
910         }
911 }
912
913 /** \brief Get an uint32 value from the input.
914  *  \memberof packmsg_input
915  *
916  * \param buf  A pointer to an input buffer iterator.
917  * \return     The uint32 value that was read from the input,
918  *             or 0 in case of an error.
919  */
920 static inline uint32_t packmsg_get_uint32(packmsg_input_t *buf) {
921         uint8_t hdr = packmsg_read_hdr_(buf);
922
923         if(hdr < 0x80) {
924                 return hdr;
925         } else if(hdr == 0xcc) {
926                 return packmsg_read_hdr_(buf);
927         } else if(hdr == 0xcd) {
928                 uint16_t val = 0;
929                 packmsg_read_data_(buf, &val, 2);
930                 return val;
931         } else if(hdr == 0xce) {
932                 uint32_t val = 0;
933                 packmsg_read_data_(buf, &val, 4);
934                 return val;
935         } else {
936                 packmsg_input_invalidate(buf);
937                 return 0;
938         }
939 }
940
941 /** \brief Get an uint64 value from the input.
942  *  \memberof packmsg_input
943  *
944  * \param buf  A pointer to an input buffer iterator.
945  * \return     The uint64 value that was read from the input,
946  *             or 0 in case of an error.
947  */
948 static inline uint64_t packmsg_get_uint64(packmsg_input_t *buf) {
949         uint8_t hdr = packmsg_read_hdr_(buf);
950
951         if(hdr < 0x80) {
952                 return hdr;
953         } else if(hdr == 0xcc) {
954                 return packmsg_read_hdr_(buf);
955         } else if(hdr == 0xcd) {
956                 uint16_t val = 0;
957                 packmsg_read_data_(buf, &val, 2);
958                 return val;
959         } else if(hdr == 0xce) {
960                 uint32_t val = 0;
961                 packmsg_read_data_(buf, &val, 4);
962                 return val;
963         } else if(hdr == 0xcf) {
964                 uint64_t val = 0;
965                 packmsg_read_data_(buf, &val, 8);
966                 return val;
967         } else {
968                 packmsg_input_invalidate(buf);
969                 return 0;
970         }
971 }
972
973 /** \brief Get a float value from the input.
974  *  \memberof packmsg_input
975  *
976  * \param buf  A pointer to an input buffer iterator.
977  * \return     The float value that was read from the input,
978  *             or 0 in case of an error.
979  */
980 static inline float packmsg_get_float(packmsg_input_t *buf) {
981         uint8_t hdr = packmsg_read_hdr_(buf);
982
983         if(hdr == 0xca) {
984                 float val;
985                 packmsg_read_data_(buf, &val, 4);
986                 return val;
987         } else {
988                 packmsg_input_invalidate(buf);
989                 return 0;
990         }
991 }
992
993 /** \brief Get a double value from the input.
994  *  \memberof packmsg_input
995  *
996  * \param buf  A pointer to an input buffer iterator.
997  * \return     The float value that was read from the input,
998  *             or 0 in case of an error.
999  */
1000 static inline double packmsg_get_double(packmsg_input_t *buf) {
1001         uint8_t hdr = packmsg_read_hdr_(buf);
1002
1003         if(hdr == 0xcb) {
1004                 double val;
1005                 packmsg_read_data_(buf, &val, 8);
1006                 return val;
1007         } else if(hdr == 0xca) {
1008                 float val;
1009                 packmsg_read_data_(buf, &val, 4);
1010                 return val;
1011         } else {
1012                 packmsg_input_invalidate(buf);
1013                 return 0;
1014         }
1015 }
1016
1017 /** \brief Get a raw pointer to a string from the input.
1018  *  \memberof packmsg_input
1019  *
1020  * This function returns the size of a string and a pointer into the input buffer itself,
1021  * to a string that is *not NUL-terminated!* This function avoids making a copy of the string,
1022  * but the application must take care to not read more than the returned number of bytes.
1023  *
1024  * \param buf       A pointer to an input buffer iterator.
1025  * \param[out] str  A pointer to a const char pointer that will be set to the start of the string,
1026  *                  or will be set to NULL in case of an error.
1027  * \return          The size of the string in bytes,
1028  *                  or 0 in case of an error.
1029  */
1030 static inline uint32_t packmsg_get_str_raw(packmsg_input_t *buf, const char **str) {
1031         assert(str);
1032
1033         uint8_t hdr = packmsg_read_hdr_(buf);
1034         uint32_t slen = 0;
1035
1036         if((hdr & 0xe0) == 0xa0) {
1037                 slen = hdr & 0x1f;
1038         } else if(hdr == 0xd9) {
1039                 packmsg_read_data_(buf, &slen, 1);
1040         } else if(hdr == 0xda) {
1041                 packmsg_read_data_(buf, &slen, 2);
1042         } else if(hdr == 0xdb) {
1043                 packmsg_read_data_(buf, &slen, 4);
1044         } else {
1045                 packmsg_input_invalidate(buf);
1046                 *str = NULL;
1047                 return 0;
1048         }
1049
1050         if(packmsg_likely(buf->len >= slen)) {
1051                 *str = (const char *)buf->ptr;
1052                 buf->ptr += slen;
1053                 buf->len -= slen;
1054                 return slen;
1055         } else {
1056                 packmsg_input_invalidate(buf);
1057                 *str = NULL;
1058                 return 0;
1059         }
1060 }
1061
1062 /** \brief Copy a string from the input into a newly allocated buffer.
1063  *  \memberof packmsg_input
1064  *
1065  * This function copies a string from the input into a buffer allocated by the library
1066  * using malloc(). The copy will be NUL-terminated.
1067  * The application is responsible for freeing the memory of the buffer using free().
1068  *
1069  * \param buf   A pointer to an input buffer iterator.
1070  *
1071  * \return      A pointer to the newly allocated buffer containing a NUL-terminated string,
1072  *              or NULL in case of an error.
1073  */
1074 static inline char *packmsg_get_str_dup(packmsg_input_t *buf) {
1075         const char *str;
1076         uint32_t slen = packmsg_get_str_raw(buf, &str);
1077
1078         if(packmsg_likely(packmsg_input_ok(buf))) {
1079                 char *dup = (char *)malloc((size_t) slen + 1);
1080
1081                 if(packmsg_likely(dup)) {
1082                         memcpy(dup, str, slen);
1083                         dup[slen] = 0;
1084                         return dup;
1085                 } else {
1086                         packmsg_input_invalidate(buf);
1087                         return NULL;
1088                 }
1089         } else {
1090                 return NULL;
1091         }
1092 }
1093
1094 /** \brief Copy a string from the input into another buffer.
1095  *  \memberof packmsg_input
1096  *
1097  * This function copies a string from the input another buffer provided by the application.
1098  * The buffer must be long enough to hold the complete string plus a terminating NUL-byte.
1099  * If the buffer is not long enough, or another error occurred,
1100  * a single NUL-byte will be written to the start of the buffer (if its size is at least one byte).
1101  *
1102  * \param buf   A pointer to an input buffer iterator.
1103  * \param data  A pointer to a buffer allocated by the application.
1104  * \param dlen  The size of the buffer pointed to by data.
1105  *
1106  * \return      The size of the string in bytes,
1107  *              or 0 in case of an error.
1108  */
1109 static inline uint32_t packmsg_get_str_copy(packmsg_input_t *buf, void *data, uint32_t dlen) {
1110         assert(data);
1111
1112         const char *str;
1113         uint32_t slen = packmsg_get_str_raw(buf, &str);
1114
1115         if(packmsg_likely(packmsg_input_ok(buf))) {
1116                 if(packmsg_likely(slen < dlen)) {
1117                         memcpy(data, str, slen);
1118                         ((char *)data)[slen] = 0;
1119                         return slen;
1120                 } else {
1121                         if(dlen) {
1122                                 *(char *)data = 0;
1123                         }
1124
1125                         packmsg_input_invalidate(buf);
1126                         return 0;
1127                 }
1128         } else {
1129                 if(dlen) {
1130                         *(char *)data = 0;
1131                 }
1132
1133                 return 0;
1134         }
1135 }
1136
1137 /** \brief Get a raw pointer to binary data from the input.
1138  *  \memberof packmsg_input
1139  *
1140  * This function returns the size of the binary data and a pointer into the input buffer itself.
1141  * This function avoids making a copy of the binary data,
1142  * but the application must take care to not read more than the returned number of bytes.
1143  *
1144  * \param buf        A pointer to an input buffer iterator.
1145  * \param[out] data  A pointer to a const void pointer that will be set to the start of the data,
1146  *                   or will be set to NULL in case of an error.
1147  * \return           The size of the data in bytes,
1148  *                   or 0 in case of an error.
1149  */
1150 static inline uint32_t packmsg_get_bin_raw(packmsg_input_t *buf, const void **data) {
1151         assert(data);
1152
1153         uint8_t hdr = packmsg_read_hdr_(buf);
1154         uint32_t dlen = 0;
1155
1156         if(hdr == 0xc4) {
1157                 packmsg_read_data_(buf, &dlen, 1);
1158         } else if(hdr == 0xc5) {
1159                 packmsg_read_data_(buf, &dlen, 2);
1160         } else if(hdr == 0xc6) {
1161                 packmsg_read_data_(buf, &dlen, 4);
1162         } else {
1163                 packmsg_input_invalidate(buf);
1164                 *data = NULL;
1165                 return 0;
1166         }
1167
1168         if(packmsg_likely(buf->len >= dlen)) {
1169                 *data = buf->ptr;
1170                 buf->ptr += dlen;
1171                 buf->len -= dlen;
1172                 return dlen;
1173         } else {
1174                 packmsg_input_invalidate(buf);
1175                 *data = NULL;
1176                 return 0;
1177         }
1178 }
1179
1180 /** \brief Copy binary data from the input into a newly allocated buffer.
1181  *  \memberof packmsg_input
1182  *
1183  * This function copies binary data from the input into a buffer allocated by the library
1184  * using malloc().
1185  * The application is responsible for freeing the memory of the buffer using free().
1186  *
1187  * \param buf        A pointer to an input buffer iterator.
1188  * \param[out] dlen  A pointer to an uint32_t that will be set to the size of the binary data.
1189  *
1190  * \return           A pointer to the newly allocated buffer containing the binary data,
1191  *                   or NULL in case of an error.
1192  */
1193 static inline void *packmsg_get_bin_dup(packmsg_input_t *buf, uint32_t *dlen) {
1194         const void *data;
1195         *dlen = packmsg_get_bin_raw(buf, &data);
1196
1197         if(packmsg_likely(packmsg_input_ok(buf))) {
1198                 char *dup = (char *)malloc(*dlen);
1199
1200                 if(packmsg_likely(dup)) {
1201                         memcpy(dup, data, *dlen);
1202                         return dup;
1203                 } else {
1204                         *dlen = 0;
1205                         packmsg_input_invalidate(buf);
1206                         return NULL;
1207                 }
1208         } else {
1209                 return NULL;
1210         }
1211 }
1212
1213 /** \brief Copy binary data from the input into another buffer.
1214  *  \memberof packmsg_input
1215  *
1216  * This function copies binary data from the input another buffer provided by the application.
1217  * The buffer must be long enough to hold all the binary data.
1218  *
1219  * \param buf     A pointer to an input buffer iterator.
1220  * \param rawbuf  A pointer to a buffer allocated by the application.
1221  * \param rlen    The size of the buffer pointed to by data.
1222  *
1223  * \return      The size of the binary data in bytes,
1224  *              or 0 in case of an error.
1225  */
1226 static inline uint32_t packmsg_get_bin_copy(packmsg_input_t *buf, void *rawbuf, uint32_t rlen) {
1227         assert(rawbuf);
1228
1229         const void *data;
1230         uint32_t dlen = packmsg_get_bin_raw(buf, &data);
1231
1232         if(packmsg_likely(packmsg_input_ok(buf))) {
1233                 if(packmsg_likely(dlen <= rlen)) {
1234                         memcpy(rawbuf, data, dlen);
1235                         return dlen;
1236                 } else {
1237                         packmsg_input_invalidate(buf);
1238                         return 0;
1239                 }
1240         } else {
1241                 return 0;
1242         }
1243 }
1244
1245 /** \brief Get a raw pointer to extension data from the input.
1246  *  \memberof packmsg_input
1247  *
1248  * This function returns the type of the extension, the size of the data
1249  * and a pointer into the input buffer itself.
1250  * This function avoids making a copy of the binary data,
1251  * but the application must take care to not read more than the returned number of bytes.
1252  *
1253  * \param buf        A pointer to an input buffer iterator.
1254  * \param[out] type  A pointer to an int8_t that will be set to the type of the extension.
1255  *                   or will be set to 0 in case of an error.
1256  * \param[out] data  A pointer to a const void pointer that will be set to the start of the data,
1257  *                   or will be set to NULL in case of an error.
1258  *
1259  * \return           The size of the data in bytes,
1260  *                   or 0 in case of an error.
1261  */
1262 static inline uint32_t packmsg_get_ext_raw(packmsg_input_t *buf, int8_t *type, const void **data) {
1263         assert(type);
1264         assert(data);
1265
1266         uint8_t hdr = packmsg_read_hdr_(buf);
1267         uint32_t dlen = 0;
1268
1269         if(hdr == 0xc7) {
1270                 packmsg_read_data_(buf, &dlen, 1);
1271         } else if(hdr == 0xc8) {
1272                 packmsg_read_data_(buf, &dlen, 2);
1273         } else if(hdr == 0xc9) {
1274                 packmsg_read_data_(buf, &dlen, 4);
1275         } else if(hdr >= 0xd4 && hdr <= 0xd8) {
1276                 dlen = 1 << (hdr - 0xd4);
1277         } else {
1278                 packmsg_input_invalidate(buf);
1279                 *type = 0;
1280                 *data = NULL;
1281                 return 0;
1282         }
1283
1284         *type = packmsg_read_hdr_(buf);
1285
1286         if(packmsg_likely(buf->len >= dlen)) {
1287                 *data = buf->ptr;
1288                 buf->ptr += dlen;
1289                 buf->len -= dlen;
1290                 return dlen;
1291         } else {
1292                 packmsg_input_invalidate(buf);
1293                 *type = 0;
1294                 *data = NULL;
1295                 return 0;
1296         }
1297 }
1298
1299 /** \brief Copy extension data from the input into a newly allocated buffer.
1300  *  \memberof packmsg_input
1301  *
1302  * This function copies extension data from the input into a buffer allocated by the library
1303  * using malloc().
1304  * The application is responsible for freeing the memory of the buffer using free().
1305  *
1306  * \param buf        A pointer to an input buffer iterator.
1307  * \param[out] type  A pointer to an int8_t that will be set to the type of the extension.
1308  *                   or will be set to 0 in case of an error.
1309  * \param[out] dlen  A pointer to an uint32_t that will be set to the size of the extension data,
1310  *                   or will be set to 0 in case of an error.
1311  *
1312  * \return           A pointer to the newly allocated buffer containing the extension data,
1313  *                   or NULL in case of an error.
1314  */
1315 static inline void *packmsg_get_ext_dup(packmsg_input_t *buf, int8_t *type, uint32_t *dlen) {
1316         assert(type);
1317
1318         const void *data;
1319         *dlen = packmsg_get_ext_raw(buf, type, &data);
1320
1321         if(packmsg_likely(packmsg_input_ok(buf))) {
1322                 char *dup = (char *)malloc(*dlen);
1323
1324                 if(packmsg_likely(dup)) {
1325                         memcpy(dup, data, *dlen);
1326                         return dup;
1327                 } else {
1328                         *type = 0;
1329                         *dlen = 0;
1330                         packmsg_input_invalidate(buf);
1331                         return NULL;
1332                 }
1333         } else {
1334                 *type = 0;
1335                 *dlen = 0;
1336                 return NULL;
1337         }
1338 }
1339
1340 /** \brief Copy extension data from the input into another buffer.
1341  *  \memberof packmsg_input
1342  *
1343  * This function copies extension data from the input another buffer provided by the application.
1344  * The buffer must be long enough to hold all the extension data.
1345  *
1346  * \param buf        A pointer to an input buffer iterator.
1347  * \param[out] type  A pointer to an int8_t that will be set to the type of the extension.
1348  *                   or will be set to 0 in case of an error.
1349  * \param rawbuf     A pointer to a buffer allocated by the application.
1350  * \param rlen       The size of the buffer pointed to by data.
1351  *
1352  * \return           The size of the extension data in bytes,
1353  *                   or 0 in case of an error.
1354  */
1355 static inline uint32_t packmsg_get_ext_copy(packmsg_input_t *buf, int8_t *type, void *rawbuf, uint32_t rlen) {
1356         assert(type);
1357         assert(rawbuf);
1358
1359         const void *data;
1360         uint32_t dlen = packmsg_get_ext_raw(buf, type, &data);
1361
1362         if(packmsg_likely(packmsg_input_ok(buf))) {
1363                 if(packmsg_likely(dlen <= rlen)) {
1364                         memcpy(rawbuf, data, dlen);
1365                         return dlen;
1366                 } else {
1367                         *type = 0;
1368                         packmsg_input_invalidate(buf);
1369                         return 0;
1370                 }
1371         } else {
1372                 *type = 0;
1373                 return 0;
1374         }
1375 }
1376
1377 /** \brief Get a map header from the output.
1378  *  \memberof packmsg_input
1379  *
1380  * This function only reads a map header, and returns the number of key-value
1381  * pairs in the map.
1382  * These key-value pairs have to be read by the application using regular
1383  * packmsg_get_*() calls.
1384  *
1385  * \param buf    A pointer to an input buffer iterator.
1386  *
1387  * \return       The number of key-value pairs in the map.
1388  */
1389 static inline uint32_t packmsg_get_map(packmsg_input_t *buf) {
1390         uint8_t hdr = packmsg_read_hdr_(buf);
1391
1392         if((hdr & 0xf0) == 0x80) {
1393                 return hdr & 0xf;
1394         } else if(hdr == 0xde) {
1395                 uint32_t dlen = 0;
1396                 packmsg_read_data_(buf, &dlen, 2);
1397                 return dlen;
1398         } else if(hdr == 0xdf) {
1399                 uint32_t dlen = 0;
1400                 packmsg_read_data_(buf, &dlen, 4);
1401                 return dlen;
1402         } else {
1403                 packmsg_input_invalidate(buf);
1404                 return 0;
1405         }
1406 }
1407
1408 /** \brief Get an array header from the output.
1409  *  \memberof packmsg_input
1410  *
1411  * This function only reads an array header, and returns the number of elements
1412  * in the array.
1413  * These elements have to be read by the application using regular
1414  * packmsg_get_*() calls.
1415  *
1416  * \param buf    A pointer to an input buffer iterator.
1417  *
1418  * \return       The number of elements in the array.
1419  */
1420 static inline uint32_t packmsg_get_array(packmsg_input_t *buf) {
1421         uint8_t hdr = packmsg_read_hdr_(buf);
1422
1423         if((hdr & 0xf0) == 0x90) {
1424                 return hdr & 0xf;
1425         } else if(hdr == 0xdc) {
1426                 uint32_t dlen = 0;
1427                 packmsg_read_data_(buf, &dlen, 2);
1428                 return dlen;
1429         } else if(hdr == 0xdd) {
1430                 uint32_t dlen = 0;
1431                 packmsg_read_data_(buf, &dlen, 4);
1432                 return dlen;
1433         } else {
1434                 packmsg_input_invalidate(buf);
1435                 return 0;
1436         }
1437 }
1438
1439 /* Type checking
1440  * =============
1441  */
1442
1443 /** \brief An enum describing the type of an element in a PackMessage message.
1444  *
1445  * This enum describes the type of an element in a PackMessage message.
1446  * In case of integers and floating point values, the type normally represents
1447  * the smallest type that can successfully hold the value of the element;
1448  * i.e. an element of type PACKMSG_INT32 can only successfully be read by
1449  * packmsg_get_int32() or packmsg_get_int64(). However, the converse it not true;
1450  * for an element of type PACKMSG_INT32, there is no guarantee
1451  * that the value is larger than would fit into an int16_t.
1452  *
1453  * PackMessage makes a clear distinction between signed and unsigned integers,
1454  * except in the case of positive fixints (values between 0 and 127 inclusive),
1455  * which can be read as both signed and unsigned.
1456  */
1457 enum packmsg_type {
1458         PACKMSG_ERROR,            /**< An invalid element was found or the input buffer is in an invalid state. */
1459         PACKMSG_NIL,              /**< The next element is a NIL. */
1460         PACKMSG_BOOL,             /**< The next element is a boolean. */
1461         PACKMSG_POSITIVE_FIXINT,  /**< The next element is an integer between 0 and 127 inclusive. */
1462         PACKMSG_INT8,             /**< The next element is a signed integer that fits in an int8_t. */
1463         PACKMSG_INT16,            /**< The next element is a signed integer that fits in an int16_t. */
1464         PACKMSG_INT32,            /**< The next element is a signed integer that fits in an int32_t. */
1465         PACKMSG_INT64,            /**< The next element is a signed integer that fits in an int64_t. */
1466         PACKMSG_UINT8,            /**< The next element is an unsigned integer that fits in an uint8_t. */
1467         PACKMSG_UINT16,           /**< The next element is an unsigned integer that fits in an uint16_t. */
1468         PACKMSG_UINT32,           /**< The next element is an unsigned integer that fits in an uint32_t. */
1469         PACKMSG_UINT64,           /**< The next element is an unsigned integer that fits in an uint64_t. */
1470         PACKMSG_FLOAT,            /**< The next element is a single precision floating point value. */
1471         PACKMSG_DOUBLE,           /**< The next element is a double precision floating point value. */
1472         PACKMSG_STR,              /**< The next element is a string. */
1473         PACKMSG_BIN,              /**< The next element is binary data. */
1474         PACKMSG_EXT,              /**< The next element is extension data. */
1475         PACKMSG_MAP,              /**< The next element is a map header. */
1476         PACKMSG_ARRAY,            /**< The next element is an array header. */
1477         PACKMSG_DONE,             /**< There are no more elements in the input buffer. */
1478 };
1479
1480 /** \brief Checks if the next element is a NIL.
1481  *  \memberof packmsg_input
1482  *
1483  * \param buf A pointer to an input buffer iterator.
1484  *
1485  * \return True if the next element can be read by packmsg_get_nil(),
1486  *         false if not or if any other error occurred.
1487  */
1488 static inline bool packmsg_is_nil(const packmsg_input_t *buf) {
1489         return packmsg_peek_hdr_(buf) == 0xc0;
1490 }
1491
1492 /** \brief Checks if the next element is a bool.
1493  *  \memberof packmsg_input
1494  *
1495  * \param buf A pointer to an input buffer iterator.
1496  *
1497  * \return True if the next element can be read by packmsg_get_nil(),
1498  *         false if not or if any other error occurred.
1499  */
1500 static inline bool packmsg_is_bool(const packmsg_input_t *buf) {
1501         return (packmsg_peek_hdr_(buf) & 0xfe) == 0xc2;
1502 }
1503
1504 /** \brief Checks if the next element is a signed integer that fits in an int8_t.
1505  *  \memberof packmsg_input
1506  *
1507  * \param buf A pointer to an input buffer iterator.
1508  *
1509  * \return True if the next element can be read by packmsg_get_int8(),
1510  *         false if not or if any other error occurred.
1511  */
1512 static inline bool packmsg_is_int8(const packmsg_input_t *buf) {
1513         uint8_t hdr = packmsg_peek_hdr_(buf);
1514         return hdr < 0x80 || hdr == 0xd0;
1515 }
1516
1517 /** \brief Checks if the next element is a signed integer that fits in an int16_t.
1518  *  \memberof packmsg_input
1519  *
1520  * \param buf A pointer to an input buffer iterator.
1521  *
1522  * \return True if the next element can be read by packmsg_get_int16(),
1523  *         false if not or if any other error occurred.
1524  */
1525 static inline bool packmsg_is_int16(const packmsg_input_t *buf) {
1526         uint8_t hdr = packmsg_peek_hdr_(buf);
1527         return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1;
1528 }
1529
1530 /** \brief Checks if the next element is a signed integer that fits in an int32_t.
1531  *  \memberof packmsg_input
1532  *
1533  * \param buf A pointer to an input buffer iterator.
1534  *
1535  * \return True if the next element can be read by packmsg_get_int32(),
1536  *         false if not or if any other error occurred.
1537  */
1538 static inline bool packmsg_is_int32(const packmsg_input_t *buf) {
1539         uint8_t hdr = packmsg_peek_hdr_(buf);
1540         return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1 || hdr == 0xd2;
1541 }
1542
1543 /** \brief Checks if the next element is a signed integer that fits in an int64_t.
1544  *  \memberof packmsg_input
1545  *
1546  * \param buf A pointer to an input buffer iterator.
1547  *
1548  * \return True if the next element can be read by packmsg_get_int64(),
1549  *         false if not or if any other error occurred.
1550  */
1551 static inline bool packmsg_is_int64(const packmsg_input_t *buf) {
1552         uint8_t hdr = packmsg_peek_hdr_(buf);
1553         return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1 || hdr == 0xd2 || hdr == 0xd3;
1554 }
1555
1556 /** \brief Checks if the next element is an unsigned integer that fits in an uint8_t.
1557  *  \memberof packmsg_input
1558  *
1559  * \param buf A pointer to an input buffer iterator.
1560  *
1561  * \return True if the next element can be read by packmsg_get_uint8(),
1562  *         false if not or if any other error occurred.
1563  */
1564 static inline bool packmsg_is_uint8(const packmsg_input_t *buf) {
1565         uint8_t hdr = packmsg_peek_hdr_(buf);
1566         return hdr < 0x80 || hdr == 0xcc;
1567 }
1568
1569 /** \brief Checks if the next element is an unsigned integer that fits in an uint16_t.
1570  *  \memberof packmsg_input
1571  *
1572  * \param buf A pointer to an input buffer iterator.
1573  *
1574  * \return True if the next element can be read by packmsg_get_uint16(),
1575  *         false if not or if any other error occurred.
1576  */
1577 static inline bool packmsg_is_uint16(const packmsg_input_t *buf) {
1578         uint8_t hdr = packmsg_peek_hdr_(buf);
1579         return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd;
1580 }
1581
1582 /** \brief Checks if the next element is an unsigned integer that fits in an uint32_t.
1583  *  \memberof packmsg_input
1584  *
1585  * \param buf A pointer to an input buffer iterator.
1586  *
1587  * \return True if the next element can be read by packmsg_get_uint32(),
1588  *         false if not or if any other error occurred.
1589  */
1590 static inline bool packmsg_is_uint32(const packmsg_input_t *buf) {
1591         uint8_t hdr = packmsg_peek_hdr_(buf);
1592         return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd || hdr == 0xce;
1593 }
1594
1595 /** \brief Checks if the next element is an unsigned integer that fits in an uint64_t.
1596  *  \memberof packmsg_input
1597  *
1598  * \param buf A pointer to an input buffer iterator.
1599  *
1600  * \return True if the next element can be read by packmsg_get_uint64(),
1601  *         false if not or if any other error occurred.
1602  */
1603 static inline bool packmsg_is_uint64(const packmsg_input_t *buf) {
1604         uint8_t hdr = packmsg_peek_hdr_(buf);
1605         return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd || hdr == 0xce || hdr == 0xcf;
1606 }
1607
1608 /** \brief Checks if the next element is a single precision floating point value.
1609  *  \memberof packmsg_input
1610  *
1611  * \param buf A pointer to an input buffer iterator.
1612  *
1613  * \return True if the next element can be read by packmsg_get_float(),
1614  *         false if not or if any other error occurred.
1615  */
1616 static inline bool packmsg_is_float(const packmsg_input_t *buf) {
1617         return packmsg_peek_hdr_(buf) == 0xca;
1618 }
1619
1620 /** \brief Checks if the next element is a single or double precision floating point value.
1621  *  \memberof packmsg_input
1622  *
1623  * \param buf A pointer to an input buffer iterator.
1624  *
1625  * \return True if the next element can be read by packmsg_get_double(),
1626  *         false if not or if any other error occurred.
1627  */
1628 static inline bool packmsg_is_double(const packmsg_input_t *buf) {
1629         uint8_t hdr = packmsg_peek_hdr_(buf);
1630         return hdr == 0xcb || hdr == 0xca;
1631 }
1632
1633 /** \brief Checks if the next element is a string.
1634  *  \memberof packmsg_input
1635  *
1636  * \param buf A pointer to an input buffer iterator.
1637  *
1638  * \return True if the next element can be read by packmsg_get_str_*(),
1639  *         false if not or if any other error occurred.
1640  */
1641 static inline bool packmsg_is_str(const packmsg_input_t *buf) {
1642         uint8_t hdr = packmsg_peek_hdr_(buf);
1643         return (hdr & 0xe0) == 0xa0 || hdr == 0xd9 || hdr == 0xda || hdr == 0xdb;
1644 }
1645
1646 /** \brief Checks if the next element is binary data.
1647  *  \memberof packmsg_input
1648  *
1649  * \param buf A pointer to an input buffer iterator.
1650  *
1651  * \return True if the next element can be read by packmsg_get_bin_*(),
1652  *         false if not or if any other error occurred.
1653  */
1654 static inline bool packmsg_is_bin(const packmsg_input_t *buf) {
1655         return (packmsg_peek_hdr_(buf) & 0xfc) == 0xc4;
1656 }
1657
1658 /** \brief Checks if the next element is extension data.
1659  *  \memberof packmsg_input
1660  *
1661  * \param buf A pointer to an input buffer iterator.
1662  *
1663  * \return True if the next element can be read by packmsg_get_ext_*(),
1664  *         false if not or if any other error occurred.
1665  */
1666 static inline bool packmsg_is_ext(const packmsg_input_t *buf) {
1667         uint8_t hdr = packmsg_peek_hdr_(buf);
1668         return (hdr >= 0xc7 && hdr <= 0xc9) || (hdr >= 0xd4 && hdr <= 0xd8);
1669 }
1670
1671 /** \brief Checks if the next element is a map header.
1672  *  \memberof packmsg_input
1673  *
1674  * \param buf A pointer to an input buffer iterator.
1675  *
1676  * \return True if the next element can be read by packmsg_get_map(),
1677  *         false if not or if any other error occurred.
1678  */
1679 static inline bool packmsg_is_map(const packmsg_input_t *buf) {
1680         uint8_t hdr = packmsg_peek_hdr_(buf);
1681         return (hdr & 0xf0) == 0x80 || hdr == 0xde || hdr == 0xdf;
1682 }
1683
1684 /** \brief Checks if the next element is an array header.
1685  *  \memberof packmsg_input
1686  *
1687  * \param buf A pointer to an input buffer iterator.
1688  *
1689  * \return True if the next element can be read by packmsg_get_array(),
1690  *         false if not or if any other error occurred.
1691  */
1692 static inline bool packmsg_is_array(const packmsg_input_t *buf) {
1693         uint8_t hdr = packmsg_peek_hdr_(buf);
1694         return (hdr & 0xf0) == 0x90 || hdr == 0xdc || hdr == 0xdd;
1695 }
1696
1697 /** \brief Checks the type of the next element.
1698  *  \memberof packmsg_input
1699  *
1700  * This function checks the next element and returns an enum packmsg_type
1701  * that describes the type of the element. If the input buffer was fully consumed
1702  * and there are no more elements left, this function will return PACKMSG_DONE.
1703  *
1704  * \param buf A pointer to an output buffer iterator.
1705  *
1706  * \return    The type of the next element, or PACKMSG_DONE if no more elements
1707  *            are present in the input buffer, or PACKMSG_ERROR if the next element
1708  *            is invalid, or if any other error occurred.
1709  */
1710 static inline enum packmsg_type packmsg_get_type(const packmsg_input_t *buf) {
1711         if(packmsg_unlikely(packmsg_done(buf))) {
1712                 return PACKMSG_DONE;
1713         }
1714
1715         uint8_t hdr = packmsg_peek_hdr_(buf);
1716
1717         switch(hdr >> 4) {
1718         case 0x0:
1719         case 0x1:
1720         case 0x2:
1721         case 0x3:
1722         case 0x4:
1723         case 0x5:
1724         case 0x6:
1725         case 0x7:
1726                 return PACKMSG_POSITIVE_FIXINT;
1727
1728         case 0x8:
1729                 return PACKMSG_MAP;
1730
1731         case 0x9:
1732                 return PACKMSG_ARRAY;
1733
1734         case 0xa:
1735         case 0xb:
1736                 return PACKMSG_STR;
1737
1738         case 0xc:
1739                 switch(hdr & 0xf) {
1740                 case 0x0:
1741                         return PACKMSG_NIL;
1742
1743                 case 0x1:
1744                         return PACKMSG_ERROR;
1745
1746                 case 0x2:
1747                 case 0x3:
1748                         return PACKMSG_BOOL;
1749
1750                 case 0x4:
1751                 case 0x5:
1752                 case 0x6:
1753                         return PACKMSG_BIN;
1754
1755                 case 0x7:
1756                 case 0x8:
1757                 case 0x9:
1758                         return PACKMSG_EXT;
1759
1760                 case 0xa:
1761                         return PACKMSG_FLOAT;
1762
1763                 case 0xb:
1764                         return PACKMSG_DOUBLE;
1765
1766                 case 0xc:
1767                         return PACKMSG_UINT8;
1768
1769                 case 0xd:
1770                         return PACKMSG_UINT16;
1771
1772                 case 0xe:
1773                         return PACKMSG_UINT32;
1774
1775                 case 0xf:
1776                         return PACKMSG_UINT64;
1777
1778                 default:
1779                         return PACKMSG_ERROR;
1780                 }
1781
1782         case 0xd:
1783                 switch(hdr & 0xf) {
1784                 case 0x0:
1785                         return PACKMSG_INT8;
1786
1787                 case 0x1:
1788                         return PACKMSG_INT16;
1789
1790                 case 0x2:
1791                         return PACKMSG_INT32;
1792
1793                 case 0x3:
1794                         return PACKMSG_INT64;
1795
1796                 case 0x4:
1797                 case 0x5:
1798                 case 0x6:
1799                 case 0x7:
1800                 case 0x8:
1801                         return PACKMSG_EXT;
1802
1803                 case 0x9:
1804                 case 0xa:
1805                 case 0xb:
1806                         return PACKMSG_STR;
1807
1808                 case 0xc:
1809                 case 0xd:
1810                         return PACKMSG_ARRAY;
1811
1812                 case 0xe:
1813                 case 0xf:
1814                         return PACKMSG_MAP;
1815
1816                 default:
1817                         return PACKMSG_ERROR;
1818                 }
1819
1820         case 0xe:
1821         case 0xf:
1822                 return PACKMSG_INT8;
1823
1824         default:
1825                 return PACKMSG_ERROR;
1826         }
1827 }
1828
1829 /** \brief Skip one element in the input
1830  *  \memberof packmsg_input
1831  *
1832  *  This function skips the next element in the input.
1833  *  If the element is a map or an array, only the map or array header is skipped,
1834  *  but not the contents of the map or array.
1835  *
1836  * \param buf A pointer to an output buffer iterator.
1837  */
1838 static inline void packmsg_skip_element(packmsg_input_t *buf) {
1839         uint8_t hdr = packmsg_read_hdr_(buf);
1840         int32_t skip = 0;
1841
1842         switch(hdr >> 4) {
1843         case 0x0:
1844         case 0x1:
1845         case 0x2:
1846         case 0x3:
1847         case 0x4:
1848         case 0x5:
1849         case 0x6:
1850         case 0x7:
1851         case 0x8:
1852         case 0x9:
1853                 return;
1854
1855         case 0xa:
1856         case 0xb:
1857                 skip = hdr & 0x1f;
1858                 break;
1859
1860         case 0xc:
1861                 switch(hdr & 0xf) {
1862                 case 0x0:
1863                 case 0x1:
1864                 case 0x2:
1865                 case 0x3:
1866                         return;
1867
1868                 case 0x4:
1869                         skip = -1;
1870                         break;
1871
1872                 case 0x5:
1873                         skip = -2;
1874                         break;
1875
1876                 case 0x6:
1877                         skip = -4;
1878                         break;
1879
1880                 case 0x7:
1881                         skip = -1;
1882                         break;
1883
1884                 case 0x8:
1885                         skip = -2;
1886                         break;
1887
1888                 case 0x9:
1889                         skip = -4;
1890                         break;
1891
1892                 case 0xa:
1893                         skip = 4;
1894                         break;
1895
1896                 case 0xb:
1897                         skip = 8;
1898                         break;
1899
1900                 case 0xc:
1901                         skip = 1;
1902                         break;
1903
1904                 case 0xd:
1905                         skip = 2;
1906                         break;
1907
1908                 case 0xe:
1909                         skip = 4;
1910                         break;
1911
1912                 case 0xf:
1913                         skip = 8;
1914                         break;
1915                 }
1916
1917                 break;
1918
1919         case 0xd:
1920                 switch(hdr & 0xf) {
1921                 case 0x0:
1922                         skip = 1;
1923                         break;
1924
1925                 case 0x1:
1926                         skip = 2;
1927                         break;
1928
1929                 case 0x2:
1930                         skip = 4;
1931                         break;
1932
1933                 case 0x3:
1934                         skip = 8;
1935                         break;
1936
1937                 case 0x4:
1938                         skip = 2;
1939                         break;
1940
1941                 case 0x5:
1942                         skip = 3;
1943                         break;
1944
1945                 case 0x6:
1946                         skip = 5;
1947                         break;
1948
1949                 case 0x7:
1950                         skip = 9;
1951                         break;
1952
1953                 case 0x8:
1954                         skip = 17;
1955                         break;
1956
1957                 case 0x9:
1958                         skip = -1;
1959                         break;
1960
1961                 case 0xa:
1962                         skip = -2;
1963                         break;
1964
1965                 case 0xb:
1966                         skip = -4;
1967                         break;
1968
1969                 case 0xc:
1970                         skip = 2;
1971                         break;
1972
1973                 case 0xd:
1974                         skip = 4;
1975                         break;
1976
1977                 case 0xe:
1978                         skip = 2;
1979                         break;
1980
1981                 case 0xf:
1982                         skip = 4;
1983                         break;
1984                 }
1985
1986                 break;
1987
1988         case 0xe:
1989         case 0xf:
1990                 return;
1991         }
1992
1993         uint32_t dlen = 0;
1994
1995         if(skip < 0) {
1996                 packmsg_read_data_(buf, &dlen, -skip);
1997
1998                 if(hdr >= 0xc7 && hdr <= 0xc9) {
1999                         dlen++;
2000                 }
2001         } else {
2002                 dlen = skip;
2003         }
2004
2005         if(packmsg_likely(buf->len >= dlen)) {
2006                 buf->ptr += dlen;
2007                 buf->len -= dlen;
2008         } else {
2009                 packmsg_input_invalidate(buf);
2010         }
2011 }
2012
2013 /** \brief Skip one object in the input
2014  *  \memberof packmsg_input
2015  *
2016  *  This function checks the type of the next element.
2017  *  In case it is a scalar value (for example, an int or a string),
2018  *  it skips just that scalar. If the next element is a map or an array,
2019  *  it will recursively skip as many objects as there are in that map or array.
2020  *
2021  * \param buf A pointer to an output buffer iterator.
2022  */
2023 static inline void packmsg_skip_object(packmsg_input_t *buf) {
2024         if(packmsg_is_array(buf)) {
2025                 uint32_t count = packmsg_get_array(buf);
2026
2027                 while(count-- && buf->len >= 0) {
2028                         packmsg_skip_object(buf);
2029                 }
2030         } else if(packmsg_is_map(buf)) {
2031                 uint32_t count = packmsg_get_map(buf);
2032
2033                 while(count-- && buf->len >= 0) {
2034                         packmsg_skip_object(buf);
2035                         packmsg_skip_object(buf);
2036                 }
2037         } else {
2038                 packmsg_skip_element(buf);
2039         }
2040 }
2041
2042 #ifdef __cplusplus
2043 }
2044 #endif