]> git.meshlink.io Git - meshlink/blob - src/packmsg.h
Add support for opening a MeshLink instance without permanent storage.
[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 likely(x) __builtin_expect(!!(x), 1)
46 #define 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 struct packmsg_output 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 struct packmsg_input 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 succesfully, 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 struct packmsg_output *buf) {
140         assert(buf);
141
142         return 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 struct packmsg_output *buf, const uint8_t *start) {
158         if(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 succesfully, 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 bool packmsg_input_ok(const struct packmsg_input *buf) {
177         assert(buf);
178
179         return 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 bool packmsg_done(const struct packmsg_input *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(struct packmsg_output *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(struct packmsg_input *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_(struct packmsg_output *buf, uint8_t hdr) {
235         assert(buf);
236         assert(buf->ptr);
237
238         if(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_(struct packmsg_output *buf, const void *data, uint32_t dlen) {
249         assert(buf);
250         assert(buf->ptr);
251         assert(data);
252
253         if(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_(struct packmsg_output *buf, uint8_t hdr, const void *data, uint32_t dlen) {
264         assert(buf);
265         assert(buf->ptr);
266         assert(data);
267
268         if(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 Add a NIL to the output.
282  *  \memberof packmsg_output
283  *
284  * \param buf  A pointer to an output buffer iterator.
285  */
286 static inline void packmsg_add_nil(struct packmsg_output *buf) {
287         packmsg_write_hdr_(buf, 0xc0);
288 }
289
290 /** \brief Add a boolean value to the output.
291  *  \memberof packmsg_output
292  *
293  * \param buf  A pointer to an output buffer iterator.
294  * \param val  The value to add.
295  */
296 static inline void packmsg_add_bool(struct packmsg_output *buf, bool val) {
297         packmsg_write_hdr_(buf, val ? 0xc3 : 0xc2);
298 }
299
300 /** \brief Add an int8 value to the output.
301  *  \memberof packmsg_output
302  *
303  * \param buf  A pointer to an output buffer iterator.
304  * \param val  The value to add.
305  */
306 static inline void packmsg_add_int8(struct packmsg_output *buf, int8_t val) {
307         if(val >= -32) {        // fixint
308                 packmsg_write_hdr_(buf, val);
309         } else {                // TODO: negative fixint
310                 packmsg_write_hdrdata_(buf, 0xd0, &val, 1);
311         }
312 }
313
314 /** \brief Add an int16 value to the output.
315  *  \memberof packmsg_output
316  *
317  * \param buf  A pointer to an output buffer iterator.
318  * \param val  The value to add.
319  */
320 static inline void packmsg_add_int16(struct packmsg_output *buf, int16_t val) {
321         if((int8_t) val != val) {
322                 packmsg_write_hdrdata_(buf, 0xd1, &val, 2);
323         } else {
324                 packmsg_add_int8(buf, val);
325         }
326 }
327
328 /** \brief Add an int32 value to the output.
329  *  \memberof packmsg_output
330  *
331  * \param buf  A pointer to an output buffer iterator.
332  * \param val  The value to add.
333  */
334 static inline void packmsg_add_int32(struct packmsg_output *buf, int32_t val) {
335         if((int16_t) val != val) {
336                 packmsg_write_hdrdata_(buf, 0xd2, &val, 4);
337         } else {
338                 packmsg_add_int16(buf, val);
339         }
340 }
341
342 /** \brief Add an int64 value to the output.
343  *  \memberof packmsg_output
344  *
345  * \param buf  A pointer to an output buffer iterator.
346  * \param val  The value to add.
347  */
348 static inline void packmsg_add_int64(struct packmsg_output *buf, int64_t val) {
349         if((int32_t) val != val) {
350                 packmsg_write_hdrdata_(buf, 0xd3, &val, 8);
351         } else {
352                 packmsg_add_int32(buf, val);
353         }
354 }
355
356 /** \brief Add a uint8 value to the output.
357  *  \memberof packmsg_output
358  *
359  * \param buf  A pointer to an output buffer iterator.
360  * \param val  The value to add.
361  */
362 static inline void packmsg_add_uint8(struct packmsg_output *buf, uint8_t val) {
363         if(val < 0x80) {        // fixint
364                 packmsg_write_hdr_(buf, val);
365         } else {
366                 packmsg_write_hdrdata_(buf, 0xcc, &val, 1);
367         }
368 }
369
370 /** \brief Add a uint16 value to the output.
371  *  \memberof packmsg_output
372  *
373  * \param buf  A pointer to an output buffer iterator.
374  * \param val  The value to add.
375  */
376 static inline void packmsg_add_uint16(struct packmsg_output *buf, uint16_t val) {
377         if(val & 0xff00) {
378                 packmsg_write_hdrdata_(buf, 0xcd, &val, 2);
379         } else {
380                 packmsg_add_uint8(buf, val);
381         }
382 }
383
384 /** \brief Add a int32 value to the output.
385  *  \memberof packmsg_output
386  *
387  * \param buf  A pointer to an output buffer iterator.
388  * \param val  The value to add.
389  */
390 static inline void packmsg_add_uint32(struct packmsg_output *buf, uint32_t val) {
391         if(val & 0xffff0000) {
392                 packmsg_write_hdrdata_(buf, 0xce, &val, 4);
393         } else {
394                 packmsg_add_uint16(buf, val);
395         }
396 }
397
398 /** \brief Add a int64 value to the output.
399  *  \memberof packmsg_output
400  *
401  * \param buf  A pointer to an output buffer iterator.
402  * \param val  The value to add.
403  */
404 static inline void packmsg_add_uint64(struct packmsg_output *buf, uint64_t val) {
405         if(val & 0xffffffff00000000) {
406                 packmsg_write_hdrdata_(buf, 0xcf, &val, 8);
407         } else {
408                 packmsg_add_uint32(buf, val);
409         }
410 }
411
412 /** \brief Add a float value to the output.
413  *  \memberof packmsg_output
414  *
415  * \param buf  A pointer to an output buffer iterator.
416  * \param val  The value to add.
417  */
418 static inline void packmsg_add_float(struct packmsg_output *buf, float val) {
419         packmsg_write_hdrdata_(buf, 0xca, &val, 4);
420 }
421
422 /** \brief Add a double value to the output.
423  *  \memberof packmsg_output
424  *
425  * \param buf  A pointer to an output buffer iterator.
426  * \param val  The value to add.
427  */
428 static inline void packmsg_add_double(struct packmsg_output *buf, double val) {
429         packmsg_write_hdrdata_(buf, 0xcb, &val, 8);
430 }
431
432 /** \brief Add a string to the output.
433  *  \memberof packmsg_output
434  *
435  * \param buf  A pointer to an output buffer iterator.
436  * \param str  The string to add. This must be a NUL-terminated string.
437  */
438 static inline void packmsg_add_str(struct packmsg_output *buf, const char *str) {
439         size_t slen = strlen(str);
440
441         if(slen < 32) {
442                 packmsg_write_hdr_(buf, 0xa0 | (uint8_t) slen);
443         } else if(slen <= 0xff) {
444                 packmsg_write_hdrdata_(buf, 0xd9, &slen, 1);
445         } else if(slen <= 0xffff) {
446                 packmsg_write_hdrdata_(buf, 0xda, &slen, 2);
447         } else if(slen <= 0xffffffff) {
448                 packmsg_write_hdrdata_(buf, 0xdb, &slen, 4);
449         } else {
450                 packmsg_output_invalidate(buf);
451                 return;
452         }
453
454         packmsg_write_data_(buf, str, slen);
455 }
456
457 /** \brief Add binary data to the output.
458  *  \memberof packmsg_output
459  *
460  * \param buf   A pointer to an output buffer iterator.
461  * \param data  A pointer to the data to add.
462  * \param dlen  The length of the data in bytes.
463  */
464 static inline void packmsg_add_bin(struct packmsg_output *buf, const void *data, uint32_t dlen) {
465         if(dlen <= 0xff) {
466                 packmsg_write_hdrdata_(buf, 0xc4, &dlen, 1);
467         } else if(dlen <= 0xffff) {
468                 packmsg_write_hdrdata_(buf, 0xc5, &dlen, 2);
469         } else if(dlen <= 0xffffffff) {
470                 packmsg_write_hdrdata_(buf, 0xc6, &dlen, 4);
471         } else {
472                 packmsg_output_invalidate(buf);
473                 return;
474         }
475
476         packmsg_write_data_(buf, data, dlen);
477 }
478
479 /** \brief Add extension data to the output.
480  *  \memberof packmsg_output
481  *
482  * \param buf   A pointer to an output buffer iterator.
483  * \param type  The extension type. Values between 0 and 127 are application specific,
484  *              values between -1 and -128 are reserved for future extensions.
485  * \param data  A pointer to the data to add.
486  * \param dlen  The length of the data in bytes.
487  */
488 static inline void packmsg_add_ext(struct packmsg_output *buf, int8_t type, const void *data, uint32_t dlen) {
489         if(dlen <= 0xff) {
490                 if(dlen == 16) {
491                         packmsg_write_hdrdata_(buf, 0xd8, &type, 1);
492                 } else if(dlen == 8) {
493                         packmsg_write_hdrdata_(buf, 0xd7, &type, 1);
494                 } else if(dlen == 4) {
495                         packmsg_write_hdrdata_(buf, 0xd6, &type, 1);
496                 } else if(dlen == 2) {
497                         packmsg_write_hdrdata_(buf, 0xd5, &type, 1);
498                 } else if(dlen == 1) {
499                         packmsg_write_hdrdata_(buf, 0xd4, &type, 1);
500                 } else {
501                         packmsg_write_hdrdata_(buf, 0xc7, &dlen, 1);
502                         packmsg_write_data_(buf, &type, 1);
503                 }
504         } else if(dlen <= 0xffff) {
505                 packmsg_write_hdrdata_(buf, 0xc8, &dlen, 2);
506                 packmsg_write_data_(buf, &type, 1);
507         } else if(dlen <= 0xffffffff) {
508                 packmsg_write_hdrdata_(buf, 0xc9, &dlen, 4);
509                 packmsg_write_data_(buf, &type, 1);
510         } else {
511                 packmsg_output_invalidate(buf);
512                 return;
513         }
514
515         packmsg_write_data_(buf, data, dlen);
516 }
517
518 /** \brief Add a map header to the output.
519  *  \memberof packmsg_output
520  *
521  * This function only adds an an indicator that the next 2 * count elements
522  * are a sequence of key-value pairs that make up the contents of the map.
523  * These key-value pairs have to be added by the application using regular
524  * packmsg_add_*() calls.
525  *
526  * \param buf    A pointer to an output buffer iterator.
527  * \param count  The number of elements in the map.
528  */
529 static inline void packmsg_add_map(struct packmsg_output *buf, uint32_t count) {
530         if(count <= 0xf) {
531                 packmsg_write_hdr_(buf, 0x80 | (uint8_t) count);
532         } else if(count <= 0xffff) {
533                 packmsg_write_hdrdata_(buf, 0xde, &count, 2);
534         } else {
535                 packmsg_write_hdrdata_(buf, 0xdf, &count, 4);
536         }
537 }
538
539 /** \brief Add an array header to the output.
540  *  \memberof packmsg_output
541  *
542  * This function only adds an an indicator that the next count elements
543  * are a sequence of elements that make up the contents of the array.
544  * These elements have to be added by the application using regular
545  * packmsg_add_*() calls.
546  *
547  * \param buf    A pointer to an output buffer iterator.
548  * \param count  The number of elements in the array.
549  */
550 static inline void packmsg_add_array(struct packmsg_output *buf, uint32_t count) {
551         if(count <= 0xf) {
552                 packmsg_write_hdr_(buf, 0x90 | (uint8_t) count);
553         } else if(count <= 0xffff) {
554                 packmsg_write_hdrdata_(buf, 0xdc, &count, 2);
555         } else {
556                 packmsg_write_hdrdata_(buf, 0xdd, &count, 4);
557         }
558 }
559
560 /* Decoding functions
561  * ==================
562  */
563
564 /** \brief Internal function, do not use. */
565 static inline uint8_t packmsg_read_hdr_(struct packmsg_input *buf) {
566         assert(buf);
567         assert(buf->ptr);
568
569         if(likely(buf->len > 0)) {
570                 uint8_t hdr = *buf->ptr;
571                 buf->ptr++;
572                 buf->len--;
573                 return hdr;
574         } else {
575                 packmsg_input_invalidate(buf);
576                 return 0xc1;
577         }
578 }
579
580 /** \brief Internal function, do not use. */
581 static inline void packmsg_read_data_(struct packmsg_input *buf, void *data, uint32_t dlen) {
582         assert(buf);
583         assert(buf->ptr);
584         assert(data);
585
586         if(likely(buf->len >= dlen)) {
587                 memcpy(data, buf->ptr, dlen);
588                 buf->ptr += dlen;
589                 buf->len -= dlen;
590         } else {
591                 packmsg_input_invalidate(buf);
592         }
593 }
594
595 /** \brief Internal function, do not use. */
596 static inline uint8_t packmsg_peek_hdr_(const struct packmsg_input *buf) {
597         assert(buf);
598         assert(buf->ptr);
599
600         if(likely(buf->len > 0)) {
601                 return *buf->ptr;
602         } else {
603                 return 0xc1;
604         }
605 }
606
607 /** \brief Get a NIL from the input.
608  *  \memberof packmsg_input
609  *
610  * This function does not return anything, but will invalidate the input interator
611  * if no NIL was succesfully consumed from the input.
612  *
613  * \param buf  A pointer to an input buffer iterator.
614  */
615 static inline void packmsg_get_nil(struct packmsg_input *buf) {
616         if(packmsg_read_hdr_(buf) != 0xc0) {
617                 packmsg_input_invalidate(buf);
618         }
619 }
620
621
622 /** \brief Get a boolean value from the input.
623  *  \memberof packmsg_input
624  *
625  * \param buf  A pointer to an input buffer iterator.
626  * \return     The boolean value that was read from the input,
627  *             or false in case of an error.
628  */
629 static inline bool packmsg_get_bool(struct packmsg_input *buf) {
630         uint8_t hdr = packmsg_read_hdr_(buf);
631
632         if(hdr == 0xc2) {
633                 return false;
634         } else if(hdr == 0xc3) {
635                 return true;
636         } else {
637                 packmsg_input_invalidate(buf);
638                 return false;
639         }
640 }
641
642 /** \brief Get an int8 value from the input.
643  *  \memberof packmsg_input
644  *
645  * \param buf  A pointer to an input buffer iterator.
646  * \return     The int8 value that was read from the input,
647  *             or 0 in case of an error.
648  */
649 static inline int8_t packmsg_get_int8(struct packmsg_input *buf) {
650         uint8_t hdr = packmsg_read_hdr_(buf);
651
652         if(hdr < 0x80 || hdr >= 0xe0) {
653                 return (int8_t)hdr;
654         } else if(hdr == 0xd0) {
655                 return packmsg_read_hdr_(buf);
656         } else {
657                 packmsg_input_invalidate(buf);
658                 return 0;
659         }
660 }
661
662 /** \brief Get an int16 value from the input.
663  *  \memberof packmsg_input
664  *
665  * \param buf  A pointer to an input buffer iterator.
666  * \return     The int16 value that was read from the input,
667  *             or 0 in case of an error.
668  */
669 static inline int16_t packmsg_get_int16(struct packmsg_input *buf) {
670         uint8_t hdr = packmsg_read_hdr_(buf);
671
672         if(hdr < 0x80 || hdr >= 0xe0) {
673                 return (int8_t)hdr;
674         } else if(hdr == 0xd0) {
675                 return (int8_t) packmsg_read_hdr_(buf);
676         } else if(hdr == 0xd1) {
677                 int16_t val = 0;
678                 packmsg_read_data_(buf, &val, 2);
679                 return val;
680         } else {
681                 packmsg_input_invalidate(buf);
682                 return 0;
683         }
684 }
685
686 /** \brief Get an int32 value from the input.
687  *  \memberof packmsg_input
688  *
689  * \param buf  A pointer to an input buffer iterator.
690  * \return     The int32 value that was read from the input,
691  *             or 0 in case of an error.
692  */
693 static inline int32_t packmsg_get_int32(struct packmsg_input *buf) {
694         uint8_t hdr = packmsg_read_hdr_(buf);
695
696         if(hdr < 0x80 || hdr >= 0xe0) {
697                 return (int8_t)hdr;
698         } else if(hdr == 0xd0) {
699                 return (int8_t) packmsg_read_hdr_(buf);
700         } else if(hdr == 0xd1) {
701                 int16_t val = 0;
702                 packmsg_read_data_(buf, &val, 2);
703                 return val;
704         } else if(hdr == 0xd2) {
705                 int32_t val = 0;
706                 packmsg_read_data_(buf, &val, 4);
707                 return val;
708         } else {
709                 packmsg_input_invalidate(buf);
710                 return 0;
711         }
712 }
713
714 /** \brief Get an int64 value from the input.
715  *  \memberof packmsg_input
716  *
717  * \param buf  A pointer to an input buffer iterator.
718  * \return     The int64 value that was read from the input,
719  *             or 0 in case of an error.
720  */
721 static inline int64_t packmsg_get_int64(struct packmsg_input *buf) {
722         uint8_t hdr = packmsg_read_hdr_(buf);
723
724         if(hdr < 0x80 || hdr >= 0xe0) {
725                 return (int8_t)hdr;
726         } else if(hdr == 0xd0) {
727                 return (int8_t) packmsg_read_hdr_(buf);
728         } else if(hdr == 0xd1) {
729                 int16_t val = 0;
730                 packmsg_read_data_(buf, &val, 2);
731                 return val;
732         } else if(hdr == 0xd2) {
733                 int32_t val = 0;
734                 packmsg_read_data_(buf, &val, 4);
735                 return val;
736         } else if(hdr == 0xd3) {
737                 int64_t val = 0;
738                 packmsg_read_data_(buf, &val, 8);
739                 return val;
740         } else {
741                 packmsg_input_invalidate(buf);
742                 return 0;
743         }
744 }
745
746 /** \brief Get an uint8 value from the input.
747  *  \memberof packmsg_input
748  *
749  * \param buf  A pointer to an input buffer iterator.
750  * \return     The uint8 value that was read from the input,
751  *             or 0 in case of an error.
752  */
753 static inline uint8_t packmsg_get_uint8(struct packmsg_input *buf) {
754         uint8_t hdr = packmsg_read_hdr_(buf);
755
756         if(hdr < 0x80) {
757                 return hdr;
758         } else if(hdr == 0xcc) {
759                 return packmsg_read_hdr_(buf);
760         } else {
761                 packmsg_input_invalidate(buf);
762                 return 0;
763         }
764 }
765
766 /** \brief Get an uint16 value from the input.
767  *  \memberof packmsg_input
768  *
769  * \param buf  A pointer to an input buffer iterator.
770  * \return     The uint16 value that was read from the input,
771  *             or 0 in case of an error.
772  */
773 static inline uint16_t packmsg_get_uint16(struct packmsg_input *buf) {
774         uint8_t hdr = packmsg_read_hdr_(buf);
775
776         if(hdr < 0x80) {
777                 return hdr;
778         } else if(hdr == 0xcc) {
779                 return packmsg_read_hdr_(buf);
780         } else if(hdr == 0xcd) {
781                 uint16_t val = 0;
782                 packmsg_read_data_(buf, &val, 2);
783                 return val;
784         } else {
785                 packmsg_input_invalidate(buf);
786                 return 0;
787         }
788 }
789
790 /** \brief Get an uint32 value from the input.
791  *  \memberof packmsg_input
792  *
793  * \param buf  A pointer to an input buffer iterator.
794  * \return     The uint32 value that was read from the input,
795  *             or 0 in case of an error.
796  */
797 static inline uint32_t packmsg_get_uint32(struct packmsg_input *buf) {
798         uint8_t hdr = packmsg_read_hdr_(buf);
799
800         if(hdr < 0x80) {
801                 return hdr;
802         } else if(hdr == 0xcc) {
803                 return packmsg_read_hdr_(buf);
804         } else if(hdr == 0xcd) {
805                 uint16_t val = 0;
806                 packmsg_read_data_(buf, &val, 2);
807                 return val;
808         } else if(hdr == 0xce) {
809                 uint32_t val = 0;
810                 packmsg_read_data_(buf, &val, 4);
811                 return val;
812         } else {
813                 packmsg_input_invalidate(buf);
814                 return 0;
815         }
816 }
817
818 /** \brief Get an uint64 value from the input.
819  *  \memberof packmsg_input
820  *
821  * \param buf  A pointer to an input buffer iterator.
822  * \return     The uint64 value that was read from the input,
823  *             or 0 in case of an error.
824  */
825 static inline uint64_t packmsg_get_uint64(struct packmsg_input *buf) {
826         uint8_t hdr = packmsg_read_hdr_(buf);
827
828         if(hdr < 0x80) {
829                 return hdr;
830         } else if(hdr == 0xcc) {
831                 return packmsg_read_hdr_(buf);
832         } else if(hdr == 0xcd) {
833                 uint16_t val = 0;
834                 packmsg_read_data_(buf, &val, 2);
835                 return val;
836         } else if(hdr == 0xce) {
837                 uint32_t val = 0;
838                 packmsg_read_data_(buf, &val, 4);
839                 return val;
840         } else if(hdr == 0xcf) {
841                 uint64_t val = 0;
842                 packmsg_read_data_(buf, &val, 8);
843                 return val;
844         } else {
845                 packmsg_input_invalidate(buf);
846                 return 0;
847         }
848 }
849
850 /** \brief Get a float value from the input.
851  *  \memberof packmsg_input
852  *
853  * \param buf  A pointer to an input buffer iterator.
854  * \return     The float value that was read from the input,
855  *             or 0 in case of an error.
856  */
857 static inline float packmsg_get_float(struct packmsg_input *buf) {
858         uint8_t hdr = packmsg_read_hdr_(buf);
859
860         if(hdr == 0xca) {
861                 float val;
862                 packmsg_read_data_(buf, &val, 4);
863                 return val;
864         } else {
865                 packmsg_input_invalidate(buf);
866                 return 0;
867         }
868 }
869
870 /** \brief Get a double value from the input.
871  *  \memberof packmsg_input
872  *
873  * \param buf  A pointer to an input buffer iterator.
874  * \return     The float value that was read from the input,
875  *             or 0 in case of an error.
876  */
877 static inline double packmsg_get_double(struct packmsg_input *buf) {
878         uint8_t hdr = packmsg_read_hdr_(buf);
879
880         if(hdr == 0xcb) {
881                 double val;
882                 packmsg_read_data_(buf, &val, 8);
883                 return val;
884         } else if(hdr == 0xca) {
885                 float val;
886                 packmsg_read_data_(buf, &val, 4);
887                 return val;
888         } else {
889                 packmsg_input_invalidate(buf);
890                 return 0;
891         }
892 }
893
894 /** \brief Get a raw pointer to a string from the input.
895  *  \memberof packmsg_input
896  *
897  * This function returns the size of a string and a pointer into the input buffer itself,
898  * to a string that is *not NUL-terminated!* This function avoids making a copy of the string,
899  * but the application must take care to not read more than the returned number of bytes.
900  *
901  * \param buf       A pointer to an input buffer iterator.
902  * \param[out] str  A pointer to a const char pointer that will be set to the start of the string,
903  *                  or will be set to NULL in case of an error.
904  * \return          The size of the string in bytes,
905  *                  or 0 in case of an error.
906  */
907 static inline uint32_t packmsg_get_str_raw(struct packmsg_input *buf, const char **str) {
908         assert(str);
909
910         uint8_t hdr = packmsg_read_hdr_(buf);
911         uint32_t slen = 0;
912
913         if((hdr & 0xe0) == 0xa0) {
914                 slen = hdr & 0x1f;
915         } else if(hdr == 0xd9) {
916                 packmsg_read_data_(buf, &slen, 1);
917         } else if(hdr == 0xda) {
918                 packmsg_read_data_(buf, &slen, 2);
919         } else if(hdr == 0xdb) {
920                 packmsg_read_data_(buf, &slen, 4);
921         } else {
922                 packmsg_input_invalidate(buf);
923                 *str = NULL;
924                 return 0;
925         }
926
927         if(likely(buf->len >= slen)) {
928                 *str = (const char *)buf->ptr;
929                 buf->ptr += slen;
930                 buf->len -= slen;
931                 return slen;
932         } else {
933                 packmsg_input_invalidate(buf);
934                 *str = NULL;
935                 return 0;
936         }
937 }
938
939 /** \brief Copy a string from the input into a newly allocated buffer.
940  *  \memberof packmsg_input
941  *
942  * This function copies a string from the input into a buffer allocated by the library
943  * using malloc(). The copy will be NUL-terminated.
944  * The application is responsible for freeing the memory of the buffer using free().
945  *
946  * \param buf   A pointer to an input buffer iterator.
947  *
948  * \return      A pointer to the newly allocated buffer containing a NUL-terminated string,
949  *              or NULL in case of an error.
950  */
951 static inline char *packmsg_get_str_dup(struct packmsg_input *buf) {
952         const char *str;
953         uint32_t slen = packmsg_get_str_raw(buf, &str);
954
955         if(likely(packmsg_input_ok(buf))) {
956                 char *dup = (char *)malloc((size_t) slen + 1);
957
958                 if(likely(dup)) {
959                         memcpy(dup, str, slen);
960                         dup[slen] = 0;
961                         return dup;
962                 } else {
963                         packmsg_input_invalidate(buf);
964                         return NULL;
965                 }
966         } else {
967                 return NULL;
968         }
969 }
970
971 /** \brief Copy a string from the input into another buffer.
972  *  \memberof packmsg_input
973  *
974  * This function copies a string from the input another buffer provided by the application.
975  * The buffer must be long enough to hold the complete string plus a terminating NUL-byte.
976  * If the buffer is not long enough, or another error occured,
977  * a single NUL-byte will be written to the start of the buffer (if its size is at least one byte).
978  *
979  * \param buf   A pointer to an input buffer iterator.
980  * \param data  A pointer to a buffer allocated by the application.
981  * \param dlen  The size of the buffer pointed to by data.
982  *
983  * \return      The size of the string in bytes,
984  *              or 0 in case of an error.
985  */
986 static inline uint32_t packmsg_get_str_copy(struct packmsg_input *buf, void *data, uint32_t dlen) {
987         assert(data);
988
989         const char *str;
990         uint32_t slen = packmsg_get_str_raw(buf, &str);
991
992         if(likely(packmsg_input_ok(buf))) {
993                 if(likely(slen < dlen)) {
994                         memcpy(data, str, slen);
995                         ((char *)data)[slen] = 0;
996                         return slen;
997                 } else {
998                         if(dlen) {
999                                 *(char *)data = 0;
1000                         }
1001
1002                         packmsg_input_invalidate(buf);
1003                         return 0;
1004                 }
1005         } else {
1006                 if(dlen) {
1007                         *(char *)data = 0;
1008                 }
1009
1010                 return 0;
1011         }
1012 }
1013
1014 /** \brief Get a raw pointer to binary data from the input.
1015  *  \memberof packmsg_input
1016  *
1017  * This function returns the size of the binary data and a pointer into the input buffer itself.
1018  * This function avoids making a copy of the binary data,
1019  * but the application must take care to not read more than the returned number of bytes.
1020  *
1021  * \param buf        A pointer to an input buffer iterator.
1022  * \param[out] data  A pointer to a const void pointer that will be set to the start of the data,
1023  *                   or will be set to NULL in case of an error.
1024  * \return           The size of the data in bytes,
1025  *                   or 0 in case of an error.
1026  */
1027 static inline uint32_t packmsg_get_bin_raw(struct packmsg_input *buf, const void **data) {
1028         assert(data);
1029
1030         uint8_t hdr = packmsg_read_hdr_(buf);
1031         uint32_t dlen = 0;
1032
1033         if(hdr == 0xc4) {
1034                 packmsg_read_data_(buf, &dlen, 1);
1035         } else if(hdr == 0xc5) {
1036                 packmsg_read_data_(buf, &dlen, 2);
1037         } else if(hdr == 0xc6) {
1038                 packmsg_read_data_(buf, &dlen, 4);
1039         } else {
1040                 packmsg_input_invalidate(buf);
1041                 *data = NULL;
1042                 return 0;
1043         }
1044
1045         if(likely(buf->len >= dlen)) {
1046                 *data = buf->ptr;
1047                 buf->ptr += dlen;
1048                 buf->len -= dlen;
1049                 return dlen;
1050         } else {
1051                 packmsg_input_invalidate(buf);
1052                 *data = NULL;
1053                 return 0;
1054         }
1055 }
1056
1057 /** \brief Copy binary data from the input into a newly allocated buffer.
1058  *  \memberof packmsg_input
1059  *
1060  * This function copies binary data from the input into a buffer allocated by the library
1061  * using malloc().
1062  * The application is responsible for freeing the memory of the buffer using free().
1063  *
1064  * \param buf        A pointer to an input buffer iterator.
1065  * \param[out] dlen  A pointer to an uint32_t that will be set to the size of the binary data.
1066  *
1067  * \return           A pointer to the newly allocated buffer containing the binary data,
1068  *                   or NULL in case of an error.
1069  */
1070 static inline void *packmsg_get_bin_dup(struct packmsg_input *buf, uint32_t *dlen) {
1071         const void *data;
1072         *dlen = packmsg_get_bin_raw(buf, &data);
1073
1074         if(likely(packmsg_input_ok(buf))) {
1075                 char *dup = (char *)malloc(*dlen);
1076
1077                 if(likely(dup)) {
1078                         memcpy(dup, data, *dlen);
1079                         return dup;
1080                 } else {
1081                         *dlen = 0;
1082                         packmsg_input_invalidate(buf);
1083                         return NULL;
1084                 }
1085         } else {
1086                 return NULL;
1087         }
1088 }
1089
1090 /** \brief Copy binary data from the input into another buffer.
1091  *  \memberof packmsg_input
1092  *
1093  * This function copies binary data from the input another buffer provided by the application.
1094  * The buffer must be long enough to hold all the binary data.
1095  *
1096  * \param buf     A pointer to an input buffer iterator.
1097  * \param rawbuf  A pointer to a buffer allocated by the application.
1098  * \param rlen    The size of the buffer pointed to by data.
1099  *
1100  * \return      The size of the binary data in bytes,
1101  *              or 0 in case of an error.
1102  */
1103 static inline uint32_t packmsg_get_bin_copy(struct packmsg_input *buf, void *rawbuf, uint32_t rlen) {
1104         assert(rawbuf);
1105
1106         const void *data;
1107         uint32_t dlen = packmsg_get_bin_raw(buf, &data);
1108
1109         if(likely(packmsg_input_ok(buf))) {
1110                 if(likely(dlen <= rlen)) {
1111                         memcpy(rawbuf, data, dlen);
1112                         return dlen;
1113                 } else {
1114                         packmsg_input_invalidate(buf);
1115                         return 0;
1116                 }
1117         } else {
1118                 return 0;
1119         }
1120 }
1121
1122 /** \brief Get a raw pointer to extension data from the input.
1123  *  \memberof packmsg_input
1124  *
1125  * This function returns the type of the extension, the size of the data
1126  * and a pointer into the input buffer itself.
1127  * This function avoids making a copy of the binary data,
1128  * but the application must take care to not read more than the returned number of bytes.
1129  *
1130  * \param buf        A pointer to an input buffer iterator.
1131  * \param[out] type  A pointer to an int8_t that will be set to the type of the extension.
1132  *                   or will be set to 0 in case of an error.
1133  * \param[out] data  A pointer to a const void pointer that will be set to the start of the data,
1134  *                   or will be set to NULL in case of an error.
1135  *
1136  * \return           The size of the data in bytes,
1137  *                   or 0 in case of an error.
1138  */
1139 static inline uint32_t packmsg_get_ext_raw(struct packmsg_input *buf, int8_t *type, const void **data) {
1140         assert(type);
1141         assert(data);
1142
1143         uint8_t hdr = packmsg_read_hdr_(buf);
1144         uint32_t dlen = 0;
1145
1146         if(hdr == 0xc7) {
1147                 packmsg_read_data_(buf, &dlen, 1);
1148         } else if(hdr == 0xc8) {
1149                 packmsg_read_data_(buf, &dlen, 2);
1150         } else if(hdr == 0xc9) {
1151                 packmsg_read_data_(buf, &dlen, 4);
1152         } else if(hdr >= 0xd4 && hdr <= 0xd8) {
1153                 dlen = 1 << (hdr - 0xd4);
1154         } else {
1155                 packmsg_input_invalidate(buf);
1156                 *type = 0;
1157                 *data = NULL;
1158                 return 0;
1159         }
1160
1161         *type = packmsg_read_hdr_(buf);
1162
1163         if(likely(buf->len >= dlen)) {
1164                 *data = buf->ptr;
1165                 buf->ptr += dlen;
1166                 buf->len -= dlen;
1167                 return dlen;
1168         } else {
1169                 packmsg_input_invalidate(buf);
1170                 *type = 0;
1171                 *data = NULL;
1172                 return 0;
1173         }
1174 }
1175
1176 /** \brief Copy extension data from the input into a newly allocated buffer.
1177  *  \memberof packmsg_input
1178  *
1179  * This function copies extension data from the input into a buffer allocated by the library
1180  * using malloc().
1181  * The application is responsible for freeing the memory of the buffer using free().
1182  *
1183  * \param buf        A pointer to an input buffer iterator.
1184  * \param[out] type  A pointer to an int8_t that will be set to the type of the extension.
1185  *                   or will be set to 0 in case of an error.
1186  * \param[out] dlen  A pointer to an uint32_t that will be set to the size of the extension data,
1187  *                   or will be set to 0 in case of an error.
1188  *
1189  * \return           A pointer to the newly allocated buffer containing the extension data,
1190  *                   or NULL in case of an error.
1191  */
1192 static inline void *packmsg_get_ext_dup(struct packmsg_input *buf, int8_t *type, uint32_t *dlen) {
1193         assert(type);
1194
1195         const void *data;
1196         *dlen = packmsg_get_ext_raw(buf, type, &data);
1197
1198         if(likely(packmsg_input_ok(buf))) {
1199                 char *dup = (char *)malloc(*dlen);
1200
1201                 if(likely(dup)) {
1202                         memcpy(dup, data, *dlen);
1203                         return dup;
1204                 } else {
1205                         *type = 0;
1206                         *dlen = 0;
1207                         packmsg_input_invalidate(buf);
1208                         return NULL;
1209                 }
1210         } else {
1211                 *type = 0;
1212                 *dlen = 0;
1213                 return NULL;
1214         }
1215 }
1216
1217 /** \brief Copy extension data from the input into another buffer.
1218  *  \memberof packmsg_input
1219  *
1220  * This function copies extension data from the input another buffer provided by the application.
1221  * The buffer must be long enough to hold all the extension data.
1222  *
1223  * \param buf        A pointer to an input buffer iterator.
1224  * \param[out] type  A pointer to an int8_t that will be set to the type of the extension.
1225  *                   or will be set to 0 in case of an error.
1226  * \param rawbuf     A pointer to a buffer allocated by the application.
1227  * \param rlen       The size of the buffer pointed to by data.
1228  *
1229  * \return           The size of the extension data in bytes,
1230  *                   or 0 in case of an error.
1231  */
1232 static inline uint32_t packmsg_get_ext_copy(struct packmsg_input *buf, int8_t *type, void *rawbuf, uint32_t rlen) {
1233         assert(type);
1234         assert(rawbuf);
1235
1236         const void *data;
1237         uint32_t dlen = packmsg_get_ext_raw(buf, type, &data);
1238
1239         if(likely(packmsg_input_ok(buf))) {
1240                 if(likely(dlen <= rlen)) {
1241                         memcpy(rawbuf, data, dlen);
1242                         return dlen;
1243                 } else {
1244                         *type = 0;
1245                         packmsg_input_invalidate(buf);
1246                         return 0;
1247                 }
1248         } else {
1249                 *type = 0;
1250                 return 0;
1251         }
1252 }
1253
1254 /** \brief Get a map header from the output.
1255  *  \memberof packmsg_input
1256  *
1257  * This function only reads a map header, and returns the number of key-value
1258  * pairs in the map.
1259  * These key-value pairs have to be read by the application using regular
1260  * packmsg_get_*() calls.
1261  *
1262  * \param buf    A pointer to an input buffer iterator.
1263  *
1264  * \return       The number of key-value pairs in the map.
1265  */
1266 static inline uint32_t packmsg_get_map(struct packmsg_input *buf) {
1267         uint8_t hdr = packmsg_read_hdr_(buf);
1268
1269         if((hdr & 0xf0) == 0x80) {
1270                 return hdr & 0xf;
1271         } else if(hdr == 0xde) {
1272                 uint32_t dlen = 0;
1273                 packmsg_read_data_(buf, &dlen, 2);
1274                 return dlen;
1275         } else if(hdr == 0xdf) {
1276                 uint32_t dlen = 0;
1277                 packmsg_read_data_(buf, &dlen, 4);
1278                 return dlen;
1279         } else {
1280                 packmsg_input_invalidate(buf);
1281                 return 0;
1282         }
1283 }
1284
1285 /** \brief Get an array header from the output.
1286  *  \memberof packmsg_input
1287  *
1288  * This function only reads an array header, and returns the number of elements
1289  * in the array.
1290  * These elements have to be read by the application using regular
1291  * packmsg_get_*() calls.
1292  *
1293  * \param buf    A pointer to an input buffer iterator.
1294  *
1295  * \return       The number of elements in the array.
1296  */
1297 static inline uint32_t packmsg_get_array(struct packmsg_input *buf) {
1298         uint8_t hdr = packmsg_read_hdr_(buf);
1299
1300         if((hdr & 0xf0) == 0x90) {
1301                 return hdr & 0xf;
1302         } else if(hdr == 0xdc) {
1303                 uint32_t dlen = 0;
1304                 packmsg_read_data_(buf, &dlen, 2);
1305                 return dlen;
1306         } else if(hdr == 0xdd) {
1307                 uint32_t dlen = 0;
1308                 packmsg_read_data_(buf, &dlen, 4);
1309                 return dlen;
1310         } else {
1311                 packmsg_input_invalidate(buf);
1312                 return 0;
1313         }
1314 }
1315
1316 /* Type checking
1317  * =============
1318  */
1319
1320 /** \brief An enum describing the type of an element in a PackMessage message.
1321  *
1322  * This enum describes the type of an element in a PackMessage message.
1323  * In case of integers and floating point values, the type normally represents
1324  * the smallest type that can succesfully hold the value of the element;
1325  * i.e. an element of type PACKMSG_INT32 can only succesfully be read by
1326  * packmsg_get_int32() or packmsg_get_int64(). However, the converse it not true;
1327  * for an element of type PACKMSG_INT32, there is no guarantee
1328  * that the value is larger than would fit into an int16_t.
1329  *
1330  * PackMessage makes a clear distinction between signed and unsigned integers,
1331  * except in the case of positive fixints (values between 0 and 127 inclusive),
1332  * which can be read as both signed and unsigned.
1333  */
1334 enum packmsg_type {
1335         PACKMSG_ERROR,            /**< An invalid element was found or the input buffer is in an invalid state. */
1336         PACKMSG_NIL,              /**< The next element is a NIL. */
1337         PACKMSG_BOOL,             /**< The next element is a boolean. */
1338         PACKMSG_POSITIVE_FIXINT,  /**< The next element is an integer between 0 and 127 inclusive. */
1339         PACKMSG_INT8,             /**< The next element is a signed integer that fits in an int8_t. */
1340         PACKMSG_INT16,            /**< The next element is a signed integer that fits in an int16_t. */
1341         PACKMSG_INT32,            /**< The next element is a signed integer that fits in an int32_t. */
1342         PACKMSG_INT64,            /**< The next element is a signed integer that fits in an int64_t. */
1343         PACKMSG_UINT8,            /**< The next element is an unsigned integer that fits in an uint8_t. */
1344         PACKMSG_UINT16,           /**< The next element is an unsigned integer that fits in an uint16_t. */
1345         PACKMSG_UINT32,           /**< The next element is an unsigned integer that fits in an uint32_t. */
1346         PACKMSG_UINT64,           /**< The next element is an unsigned integer that fits in an uint64_t. */
1347         PACKMSG_FLOAT,            /**< The next element is a single precision floating point value. */
1348         PACKMSG_DOUBLE,           /**< The next element is a double precision floating point value. */
1349         PACKMSG_STR,              /**< The next element is a string. */
1350         PACKMSG_BIN,              /**< The next element is binary data. */
1351         PACKMSG_EXT,              /**< The next element is extension data. */
1352         PACKMSG_MAP,              /**< The next element is a map header. */
1353         PACKMSG_ARRAY,            /**< The next element is an array header. */
1354         PACKMSG_DONE,             /**< There are no more elements in the input buffer. */
1355 };
1356
1357 /** \brief Checks if the next element is a NIL.
1358  *  \memberof packmsg_input
1359  *
1360  * \param buf A pointer to an input buffer iterator.
1361  *
1362  * \return True if the next element can be read by packmsg_get_nil(),
1363  *         false if not or if any other error occurred.
1364  */
1365 static inline bool packmsg_is_nil(const struct packmsg_input *buf) {
1366         return packmsg_peek_hdr_(buf) == 0xc0;
1367 }
1368
1369 /** \brief Checks if the next element is a bool.
1370  *  \memberof packmsg_input
1371  *
1372  * \param buf A pointer to an input buffer iterator.
1373  *
1374  * \return True if the next element can be read by packmsg_get_nil(),
1375  *         false if not or if any other error occurred.
1376  */
1377 static inline bool packmsg_is_bool(const struct packmsg_input *buf) {
1378         return (packmsg_peek_hdr_(buf) & 0xfe) == 0xc2;
1379 }
1380
1381 /** \brief Checks if the next element is a signed integer that fits in an int8_t.
1382  *  \memberof packmsg_input
1383  *
1384  * \param buf A pointer to an input buffer iterator.
1385  *
1386  * \return True if the next element can be read by packmsg_get_int8(),
1387  *         false if not or if any other error occurred.
1388  */
1389 static inline bool packmsg_is_int8(const struct packmsg_input *buf) {
1390         uint8_t hdr = packmsg_peek_hdr_(buf);
1391         return hdr < 0x80 || hdr == 0xd0;
1392 }
1393
1394 /** \brief Checks if the next element is a signed integer that fits in an int16_t.
1395  *  \memberof packmsg_input
1396  *
1397  * \param buf A pointer to an input buffer iterator.
1398  *
1399  * \return True if the next element can be read by packmsg_get_int16(),
1400  *         false if not or if any other error occurred.
1401  */
1402 static inline bool packmsg_is_int16(const struct packmsg_input *buf) {
1403         uint8_t hdr = packmsg_peek_hdr_(buf);
1404         return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1;
1405 }
1406
1407 /** \brief Checks if the next element is a signed integer that fits in an int32_t.
1408  *  \memberof packmsg_input
1409  *
1410  * \param buf A pointer to an input buffer iterator.
1411  *
1412  * \return True if the next element can be read by packmsg_get_int32(),
1413  *         false if not or if any other error occurred.
1414  */
1415 static inline bool packmsg_is_int32(const struct packmsg_input *buf) {
1416         uint8_t hdr = packmsg_peek_hdr_(buf);
1417         return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1 || hdr == 0xd2;
1418 }
1419
1420 /** \brief Checks if the next element is a signed integer that fits in an int64_t.
1421  *  \memberof packmsg_input
1422  *
1423  * \param buf A pointer to an input buffer iterator.
1424  *
1425  * \return True if the next element can be read by packmsg_get_int64(),
1426  *         false if not or if any other error occurred.
1427  */
1428 static inline bool packmsg_is_int64(const struct packmsg_input *buf) {
1429         uint8_t hdr = packmsg_peek_hdr_(buf);
1430         return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1 || hdr == 0xd2 || hdr == 0xd3;
1431 }
1432
1433 /** \brief Checks if the next element is an unsigned integer that fits in an uint8_t.
1434  *  \memberof packmsg_input
1435  *
1436  * \param buf A pointer to an input buffer iterator.
1437  *
1438  * \return True if the next element can be read by packmsg_get_uint8(),
1439  *         false if not or if any other error occurred.
1440  */
1441 static inline bool packmsg_is_uint8(const struct packmsg_input *buf) {
1442         uint8_t hdr = packmsg_peek_hdr_(buf);
1443         return hdr < 0x80 || hdr == 0xcc;
1444 }
1445
1446 /** \brief Checks if the next element is an unsigned integer that fits in an uint16_t.
1447  *  \memberof packmsg_input
1448  *
1449  * \param buf A pointer to an input buffer iterator.
1450  *
1451  * \return True if the next element can be read by packmsg_get_uint16(),
1452  *         false if not or if any other error occurred.
1453  */
1454 static inline bool packmsg_is_uint16(const struct packmsg_input *buf) {
1455         uint8_t hdr = packmsg_peek_hdr_(buf);
1456         return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd;
1457 }
1458
1459 /** \brief Checks if the next element is an unsigned integer that fits in an uint32_t.
1460  *  \memberof packmsg_input
1461  *
1462  * \param buf A pointer to an input buffer iterator.
1463  *
1464  * \return True if the next element can be read by packmsg_get_uint32(),
1465  *         false if not or if any other error occurred.
1466  */
1467 static inline bool packmsg_is_uint32(const struct packmsg_input *buf) {
1468         uint8_t hdr = packmsg_peek_hdr_(buf);
1469         return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd || hdr == 0xce;
1470 }
1471
1472 /** \brief Checks if the next element is an unsigned integer that fits in an uint64_t.
1473  *  \memberof packmsg_input
1474  *
1475  * \param buf A pointer to an input buffer iterator.
1476  *
1477  * \return True if the next element can be read by packmsg_get_uint64(),
1478  *         false if not or if any other error occurred.
1479  */
1480 static inline bool packmsg_is_uint64(const struct packmsg_input *buf) {
1481         uint8_t hdr = packmsg_peek_hdr_(buf);
1482         return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd || hdr == 0xce || hdr == 0xcf;
1483 }
1484
1485 /** \brief Checks if the next element is a single precision floating point value.
1486  *  \memberof packmsg_input
1487  *
1488  * \param buf A pointer to an input buffer iterator.
1489  *
1490  * \return True if the next element can be read by packmsg_get_float(),
1491  *         false if not or if any other error occurred.
1492  */
1493 static inline bool packmsg_is_float(const struct packmsg_input *buf) {
1494         return packmsg_peek_hdr_(buf) == 0xca;
1495 }
1496
1497 /** \brief Checks if the next element is a single or double precision floating point value.
1498  *  \memberof packmsg_input
1499  *
1500  * \param buf A pointer to an input buffer iterator.
1501  *
1502  * \return True if the next element can be read by packmsg_get_double(),
1503  *         false if not or if any other error occurred.
1504  */
1505 static inline bool packmsg_is_double(const struct packmsg_input *buf) {
1506         uint8_t hdr = packmsg_peek_hdr_(buf);
1507         return hdr == 0xcb || hdr == 0xca;
1508 }
1509
1510 /** \brief Checks if the next element is a string.
1511  *  \memberof packmsg_input
1512  *
1513  * \param buf A pointer to an input buffer iterator.
1514  *
1515  * \return True if the next element can be read by packmsg_get_str_*(),
1516  *         false if not or if any other error occurred.
1517  */
1518 static inline bool packmsg_is_str(const struct packmsg_input *buf) {
1519         uint8_t hdr = packmsg_peek_hdr_(buf);
1520         return (hdr & 0xe0) == 0xa0 || hdr == 0xd9 || hdr == 0xda || hdr == 0xdb;
1521 }
1522
1523 /** \brief Checks if the next element is binary data.
1524  *  \memberof packmsg_input
1525  *
1526  * \param buf A pointer to an input buffer iterator.
1527  *
1528  * \return True if the next element can be read by packmsg_get_bin_*(),
1529  *         false if not or if any other error occurred.
1530  */
1531 static inline bool packmsg_is_bin(const struct packmsg_input *buf) {
1532         return (packmsg_peek_hdr_(buf) & 0xfc) == 0xc4;
1533 }
1534
1535 /** \brief Checks if the next element is extension data.
1536  *  \memberof packmsg_input
1537  *
1538  * \param buf A pointer to an input buffer iterator.
1539  *
1540  * \return True if the next element can be read by packmsg_get_ext_*(),
1541  *         false if not or if any other error occurred.
1542  */
1543 static inline bool packmsg_is_ext(const struct packmsg_input *buf) {
1544         uint8_t hdr = packmsg_peek_hdr_(buf);
1545         return (hdr >= 0xc7 && hdr <= 0xc9) || (hdr >= 0xd4 && hdr <= 0xd8);
1546 }
1547
1548 /** \brief Checks if the next element is a map header.
1549  *  \memberof packmsg_input
1550  *
1551  * \param buf A pointer to an input buffer iterator.
1552  *
1553  * \return True if the next element can be read by packmsg_get_map(),
1554  *         false if not or if any other error occurred.
1555  */
1556 static inline bool packmsg_is_map(const struct packmsg_input *buf) {
1557         uint8_t hdr = packmsg_peek_hdr_(buf);
1558         return (hdr & 0xf0) == 0x80 || hdr == 0xde || hdr == 0xdf;
1559 }
1560
1561 /** \brief Checks if the next element is an array header.
1562  *  \memberof packmsg_input
1563  *
1564  * \param buf A pointer to an input buffer iterator.
1565  *
1566  * \return True if the next element can be read by packmsg_get_array(),
1567  *         false if not or if any other error occurred.
1568  */
1569 static inline bool packmsg_is_array(const struct packmsg_input *buf) {
1570         uint8_t hdr = packmsg_peek_hdr_(buf);
1571         return (hdr & 0xf0) == 0x90 || hdr == 0xdc || hdr == 0xdd;
1572 }
1573
1574 /** \brief Checks the type of the next element.
1575  *  \memberof packmsg_input
1576  *
1577  * This function checks the next element and returns an enum packmsg_type
1578  * that describes the type of the element. If the input buffer was fully consumed
1579  * and there are no more elements left, this function will return PACKMSG_DONE.
1580  *
1581  * \param buf A pointer to an output buffer iterator.
1582  *
1583  * \return    The type of the next element, or PACKMSG_DONE if no more elements
1584  *            are present in the input buffer, or PACKMSG_ERROR if the next element
1585  *            is invalid, or if any other error occurred.
1586  */
1587 static inline enum packmsg_type packmsg_get_type(const struct packmsg_input *buf) {
1588         if(unlikely(packmsg_done(buf))) {
1589                 return PACKMSG_DONE;
1590         }
1591
1592         uint8_t hdr = packmsg_peek_hdr_(buf);
1593
1594         switch(hdr >> 4) {
1595         case 0x0:
1596         case 0x1:
1597         case 0x2:
1598         case 0x3:
1599         case 0x4:
1600         case 0x5:
1601         case 0x6:
1602         case 0x7:
1603                 return PACKMSG_POSITIVE_FIXINT;
1604
1605         case 0x8:
1606                 return PACKMSG_MAP;
1607
1608         case 0x9:
1609                 return PACKMSG_ARRAY;
1610
1611         case 0xa:
1612         case 0xb:
1613                 return PACKMSG_STR;
1614
1615         case 0xc:
1616                 switch(hdr & 0xf) {
1617                 case 0x0:
1618                         return PACKMSG_NIL;
1619
1620                 case 0x1:
1621                         return PACKMSG_ERROR;
1622
1623                 case 0x2:
1624                 case 0x3:
1625                         return PACKMSG_BOOL;
1626
1627                 case 0x4:
1628                 case 0x5:
1629                 case 0x6:
1630                         return PACKMSG_BIN;
1631
1632                 case 0x7:
1633                 case 0x8:
1634                 case 0x9:
1635                         return PACKMSG_EXT;
1636
1637                 case 0xa:
1638                         return PACKMSG_FLOAT;
1639
1640                 case 0xb:
1641                         return PACKMSG_DOUBLE;
1642
1643                 case 0xc:
1644                         return PACKMSG_UINT8;
1645
1646                 case 0xd:
1647                         return PACKMSG_UINT16;
1648
1649                 case 0xe:
1650                         return PACKMSG_UINT32;
1651
1652                 case 0xf:
1653                         return PACKMSG_UINT64;
1654
1655                 default:
1656                         return PACKMSG_ERROR;
1657                 }
1658
1659         case 0xd:
1660                 switch(hdr & 0xf) {
1661                 case 0x0:
1662                         return PACKMSG_INT8;
1663
1664                 case 0x1:
1665                         return PACKMSG_INT16;
1666
1667                 case 0x2:
1668                         return PACKMSG_INT32;
1669
1670                 case 0x3:
1671                         return PACKMSG_INT64;
1672
1673                 case 0x4:
1674                 case 0x5:
1675                 case 0x6:
1676                 case 0x7:
1677                 case 0x8:
1678                         return PACKMSG_EXT;
1679
1680                 case 0x9:
1681                 case 0xa:
1682                 case 0xb:
1683                         return PACKMSG_STR;
1684
1685                 case 0xc:
1686                 case 0xd:
1687                         return PACKMSG_ARRAY;
1688
1689                 case 0xe:
1690                 case 0xf:
1691                         return PACKMSG_MAP;
1692
1693                 default:
1694                         return PACKMSG_ERROR;
1695                 }
1696
1697         case 0xe:
1698         case 0xf:
1699                 return PACKMSG_INT8;
1700
1701         default:
1702                 return PACKMSG_ERROR;
1703         }
1704 }
1705
1706 /** \brief Skip one element in the input
1707  *  \memberof packmsg_input
1708  *
1709  *  This function skips the next element in the input.
1710  *  If the element is a map or an array, only the map or array header is skipped,
1711  *  but not the contents of the map or array.
1712  *
1713  * \param buf A pointer to an output buffer iterator.
1714  */
1715 static inline void packmsg_skip_element(struct packmsg_input *buf) {
1716         uint8_t hdr = packmsg_read_hdr_(buf);
1717         ptrdiff_t skip = 0;
1718
1719         switch(hdr >> 4) {
1720         case 0x0:
1721         case 0x1:
1722         case 0x2:
1723         case 0x3:
1724         case 0x4:
1725         case 0x5:
1726         case 0x6:
1727         case 0x7:
1728         case 0x8:
1729         case 0x9:
1730         case 0xa:
1731         case 0xb:
1732                 return;
1733
1734         case 0xc:
1735                 switch(hdr & 0xf) {
1736                 case 0x0:
1737                 case 0x1:
1738                 case 0x2:
1739                 case 0x3:
1740                         return;
1741
1742                 case 0x4:
1743                         skip = -1;
1744                         break;
1745
1746                 case 0x5:
1747                         skip = -2;
1748                         break;
1749
1750                 case 0x6:
1751                         skip = -4;
1752                         break;
1753
1754                 case 0x7:
1755                         skip = -1;
1756                         break;
1757
1758                 case 0x8:
1759                         skip = -2;
1760                         break;
1761
1762                 case 0x9:
1763                         skip = -4;
1764                         break;
1765
1766                 case 0xa:
1767                         skip = 4;
1768                         break;
1769
1770                 case 0xb:
1771                         skip = 8;
1772                         break;
1773
1774                 case 0xc:
1775                         skip = 1;
1776                         break;
1777
1778                 case 0xd:
1779                         skip = 2;
1780                         break;
1781
1782                 case 0xe:
1783                         skip = 4;
1784                         break;
1785
1786                 case 0xf:
1787                         skip = 8;
1788                         break;
1789                 }
1790
1791                 break;
1792
1793         case 0xd:
1794                 switch(hdr & 0xf) {
1795                 case 0x0:
1796                         skip = 1;
1797                         break;
1798
1799                 case 0x1:
1800                         skip = 2;
1801                         break;
1802
1803                 case 0x2:
1804                         skip = 4;
1805                         break;
1806
1807                 case 0x3:
1808                         skip = 8;
1809                         break;
1810
1811                 case 0x4:
1812                         skip = 2;
1813                         break;
1814
1815                 case 0x5:
1816                         skip = 3;
1817                         break;
1818
1819                 case 0x6:
1820                         skip = 5;
1821                         break;
1822
1823                 case 0x7:
1824                         skip = 9;
1825                         break;
1826
1827                 case 0x8:
1828                         skip = 17;
1829                         break;
1830
1831                 case 0x9:
1832                         skip = -1;
1833                         break;
1834
1835                 case 0xa:
1836                         skip = -2;
1837                         break;
1838
1839                 case 0xb:
1840                         skip = -4;
1841                         break;
1842
1843                 case 0xc:
1844                         skip = -2;
1845                         break;
1846
1847                 case 0xd:
1848                         skip = -4;
1849                         break;
1850
1851                 case 0xe:
1852                         skip = -2;
1853                         break;
1854
1855                 case 0xf:
1856                         skip = -4;
1857                         break;
1858                 }
1859
1860                 break;
1861
1862         case 0xe:
1863         case 0xf:
1864                 return;
1865         }
1866
1867         uint32_t dlen;
1868
1869         if(skip < 0) {
1870                 packmsg_read_data_(buf, &dlen, -skip);
1871
1872                 if(hdr >= 0xc7 && hdr <= 0xc9) {
1873                         dlen++;
1874                 }
1875         } else {
1876                 dlen = skip;
1877         }
1878
1879         if(likely(buf->len >= dlen)) {
1880                 buf->ptr += dlen;
1881                 buf->len -= dlen;
1882         } else {
1883                 packmsg_input_invalidate(buf);
1884         }
1885 }
1886
1887 /** \brief Skip one object in the input
1888  *  \memberof packmsg_input
1889  *
1890  *  This function checks the type of the next element.
1891  *  In case it is a scalar value (for example, an int or a string),
1892  *  it skips just that scalar. If the next element is a map or an array,
1893  *  it will recursively skip as many objects as there are in that map or array.
1894  *
1895  * \param buf A pointer to an output buffer iterator.
1896  */
1897 static inline void packmsg_skip_object(struct packmsg_input *buf) {
1898         if(packmsg_is_array(buf)) {
1899                 uint32_t count = packmsg_get_array(buf);
1900
1901                 while(count-- && buf->len >= 0) {
1902                         packmsg_skip_object(buf);
1903                 }
1904         } else if(packmsg_is_map(buf)) {
1905                 uint32_t count = packmsg_get_map(buf);
1906
1907                 while(count-- && buf->len >= 0) {
1908                         packmsg_skip_object(buf);
1909                         packmsg_skip_object(buf);
1910                 }
1911         } else {
1912                 packmsg_skip_object(buf);
1913         }
1914 }
1915
1916 #undef likely
1917 #undef unlikely
1918
1919 #ifdef __cplusplus
1920 }
1921 #endif