4 SPDX-License-Identifier: BSD-3-Clause
6 packmsg.h -- Little-endian MessagePack implementation, optimized for speed
7 Copyright (C) 2018 Guus Sliepen <guus@tinc-vpn.org>
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
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.
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
45 #define likely(x) __builtin_expect(!!(x), 1)
46 #define unlikely(x) __builtin_expect(!!(x), 0)
48 /** \mainpage PackMessage, a safe and fast header-only C library for little-endian MessagePack encoding and decoding.
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.
54 * PackMessage is *safe*:
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.
62 * PackMessage is *fast*:
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.
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.
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.
92 * This is an example of how to encode and decode the equivalent of the JSON object `{"compact": true, "schema": 0}`
100 /** \brief Iterator for PackMessage output.
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.
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. */
112 /** \brief Iterator for PackMessage input.
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.
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. */
128 /** \brief Check if the PackMessage output buffer is in a valid state.
129 * \memberof packmsg_output
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.
134 * \param buf A pointer to an output buffer iterator.
136 * \return True if all write operations performed on the output buffer so far have completed successfully,
137 * false if any error has occurred.
139 static inline bool packmsg_output_ok(const struct packmsg_output *buf) {
142 return likely(buf->len >= 0);
145 /** \brief Calculate the amount of bytes written to the output buffer.
146 * \memberof packmsg_output
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.
151 * \param buf A pointer to an output buffer iterator.
152 * \param start A pointer to the start of the output buffer.
154 * \return The total amount of bytes written to the output buffer,
155 * or 0 if any error has occurred.
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;
165 /** \brief Check if the PackMessage input buffer is in a valid state.
166 * \memberof packmsg_input
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.
171 * \param buf A pointer to an input buffer iterator.
173 * \return True if all read operations performed on the input buffer so far have completed successfully,
174 * false if any error has occurred.
176 static inline bool packmsg_input_ok(const struct packmsg_input *buf) {
179 return likely(buf->len >= 0);
182 /** \brief Check if the PackMessage input buffer has been read completely.
183 * \memberof packmsg_input
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.
189 * \param buf A pointer to an input buffer iterator.
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.
195 static inline bool packmsg_done(const struct packmsg_input *buf) {
198 return buf->len == 0;
201 /* Invalidation functions
202 * ======================
205 /** \brief Invalidate an output iterator.
206 * \memberof packmsg_output
208 * This function invalidates an output iterator. This signals that an error occurred,
209 * and prevents further output to be written.
211 * \param buf A pointer to an output buffer iterator.
213 static inline void packmsg_output_invalidate(struct packmsg_output *buf) {
217 /** \brief Invalidate an input iterator.
218 * \memberof packmsg_input
220 * This function invalidates an input iterator. This signals that an error occurred,
221 * and prevents further input to be read.
223 * \param buf A pointer to an input buffer iterator.
225 static inline void packmsg_input_invalidate(struct packmsg_input *buf) {
229 /* Encoding functions
233 /** \brief Internal function, do not use. */
234 static inline void packmsg_write_hdr_(struct packmsg_output *buf, uint8_t hdr) {
238 if(likely(buf->len > 0)) {
243 packmsg_output_invalidate(buf);
247 /** \brief Internal function, do not use. */
248 static inline void packmsg_write_data_(struct packmsg_output *buf, const void *data, uint32_t dlen) {
253 if(likely(buf->len >= dlen)) {
254 memcpy(buf->ptr, data, dlen);
258 packmsg_output_invalidate(buf);
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) {
268 if(likely(buf->len > dlen)) {
273 memcpy(buf->ptr, data, dlen);
277 packmsg_output_invalidate(buf);
281 /** \brief Add a NIL to the output.
282 * \memberof packmsg_output
284 * \param buf A pointer to an output buffer iterator.
286 static inline void packmsg_add_nil(struct packmsg_output *buf) {
287 packmsg_write_hdr_(buf, 0xc0);
290 /** \brief Add a boolean value to the output.
291 * \memberof packmsg_output
293 * \param buf A pointer to an output buffer iterator.
294 * \param val The value to add.
296 static inline void packmsg_add_bool(struct packmsg_output *buf, bool val) {
297 packmsg_write_hdr_(buf, val ? 0xc3 : 0xc2);
300 /** \brief Add an int8 value to the output.
301 * \memberof packmsg_output
303 * \param buf A pointer to an output buffer iterator.
304 * \param val The value to add.
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);
314 /** \brief Add an int16 value to the output.
315 * \memberof packmsg_output
317 * \param buf A pointer to an output buffer iterator.
318 * \param val The value to add.
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);
324 packmsg_add_int8(buf, val);
328 /** \brief Add an int32 value to the output.
329 * \memberof packmsg_output
331 * \param buf A pointer to an output buffer iterator.
332 * \param val The value to add.
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);
338 packmsg_add_int16(buf, val);
342 /** \brief Add an int64 value to the output.
343 * \memberof packmsg_output
345 * \param buf A pointer to an output buffer iterator.
346 * \param val The value to add.
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);
352 packmsg_add_int32(buf, val);
356 /** \brief Add a uint8 value to the output.
357 * \memberof packmsg_output
359 * \param buf A pointer to an output buffer iterator.
360 * \param val The value to add.
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);
366 packmsg_write_hdrdata_(buf, 0xcc, &val, 1);
370 /** \brief Add a uint16 value to the output.
371 * \memberof packmsg_output
373 * \param buf A pointer to an output buffer iterator.
374 * \param val The value to add.
376 static inline void packmsg_add_uint16(struct packmsg_output *buf, uint16_t val) {
378 packmsg_write_hdrdata_(buf, 0xcd, &val, 2);
380 packmsg_add_uint8(buf, val);
384 /** \brief Add a int32 value to the output.
385 * \memberof packmsg_output
387 * \param buf A pointer to an output buffer iterator.
388 * \param val The value to add.
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);
394 packmsg_add_uint16(buf, val);
398 /** \brief Add a int64 value to the output.
399 * \memberof packmsg_output
401 * \param buf A pointer to an output buffer iterator.
402 * \param val The value to add.
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);
408 packmsg_add_uint32(buf, val);
412 /** \brief Add a float value to the output.
413 * \memberof packmsg_output
415 * \param buf A pointer to an output buffer iterator.
416 * \param val The value to add.
418 static inline void packmsg_add_float(struct packmsg_output *buf, float val) {
419 packmsg_write_hdrdata_(buf, 0xca, &val, 4);
422 /** \brief Add a double value to the output.
423 * \memberof packmsg_output
425 * \param buf A pointer to an output buffer iterator.
426 * \param val The value to add.
428 static inline void packmsg_add_double(struct packmsg_output *buf, double val) {
429 packmsg_write_hdrdata_(buf, 0xcb, &val, 8);
432 /** \brief Add a string to the output.
433 * \memberof packmsg_output
435 * \param buf A pointer to an output buffer iterator.
436 * \param str The string to add. This must be a NUL-terminated string.
438 static inline void packmsg_add_str(struct packmsg_output *buf, const char *str) {
439 size_t slen = strlen(str);
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);
450 packmsg_output_invalidate(buf);
454 packmsg_write_data_(buf, str, slen);
457 /** \brief Add binary data to the output.
458 * \memberof packmsg_output
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.
464 static inline void packmsg_add_bin(struct packmsg_output *buf, const void *data, uint32_t dlen) {
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);
472 packmsg_output_invalidate(buf);
476 packmsg_write_data_(buf, data, dlen);
479 /** \brief Add extension data to the output.
480 * \memberof packmsg_output
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.
488 static inline void packmsg_add_ext(struct packmsg_output *buf, int8_t type, const void *data, uint32_t dlen) {
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);
501 packmsg_write_hdrdata_(buf, 0xc7, &dlen, 1);
502 packmsg_write_data_(buf, &type, 1);
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);
511 packmsg_output_invalidate(buf);
515 packmsg_write_data_(buf, data, dlen);
518 /** \brief Add a map header to the output.
519 * \memberof packmsg_output
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.
526 * \param buf A pointer to an output buffer iterator.
527 * \param count The number of elements in the map.
529 static inline void packmsg_add_map(struct packmsg_output *buf, uint32_t count) {
531 packmsg_write_hdr_(buf, 0x80 | (uint8_t) count);
532 } else if(count <= 0xffff) {
533 packmsg_write_hdrdata_(buf, 0xde, &count, 2);
535 packmsg_write_hdrdata_(buf, 0xdf, &count, 4);
539 /** \brief Add an array header to the output.
540 * \memberof packmsg_output
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.
547 * \param buf A pointer to an output buffer iterator.
548 * \param count The number of elements in the array.
550 static inline void packmsg_add_array(struct packmsg_output *buf, uint32_t count) {
552 packmsg_write_hdr_(buf, 0x90 | (uint8_t) count);
553 } else if(count <= 0xffff) {
554 packmsg_write_hdrdata_(buf, 0xdc, &count, 2);
556 packmsg_write_hdrdata_(buf, 0xdd, &count, 4);
560 /* Decoding functions
564 /** \brief Internal function, do not use. */
565 static inline uint8_t packmsg_read_hdr_(struct packmsg_input *buf) {
569 if(likely(buf->len > 0)) {
570 uint8_t hdr = *buf->ptr;
575 packmsg_input_invalidate(buf);
580 /** \brief Internal function, do not use. */
581 static inline void packmsg_read_data_(struct packmsg_input *buf, void *data, uint32_t dlen) {
586 if(likely(buf->len >= dlen)) {
587 memcpy(data, buf->ptr, dlen);
591 packmsg_input_invalidate(buf);
595 /** \brief Internal function, do not use. */
596 static inline uint8_t packmsg_peek_hdr_(const struct packmsg_input *buf) {
600 if(likely(buf->len > 0)) {
607 /** \brief Get a NIL from the input.
608 * \memberof packmsg_input
610 * This function does not return anything, but will invalidate the input interator
611 * if no NIL was succesfully consumed from the input.
613 * \param buf A pointer to an input buffer iterator.
615 static inline void packmsg_get_nil(struct packmsg_input *buf) {
616 if(packmsg_read_hdr_(buf) != 0xc0) {
617 packmsg_input_invalidate(buf);
622 /** \brief Get a boolean value from the input.
623 * \memberof packmsg_input
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.
629 static inline bool packmsg_get_bool(struct packmsg_input *buf) {
630 uint8_t hdr = packmsg_read_hdr_(buf);
634 } else if(hdr == 0xc3) {
637 packmsg_input_invalidate(buf);
642 /** \brief Get an int8 value from the input.
643 * \memberof packmsg_input
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.
649 static inline int8_t packmsg_get_int8(struct packmsg_input *buf) {
650 uint8_t hdr = packmsg_read_hdr_(buf);
652 if(hdr < 0x80 || hdr >= 0xe0) {
654 } else if(hdr == 0xd0) {
655 return packmsg_read_hdr_(buf);
657 packmsg_input_invalidate(buf);
662 /** \brief Get an int16 value from the input.
663 * \memberof packmsg_input
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.
669 static inline int16_t packmsg_get_int16(struct packmsg_input *buf) {
670 uint8_t hdr = packmsg_read_hdr_(buf);
672 if(hdr < 0x80 || hdr >= 0xe0) {
674 } else if(hdr == 0xd0) {
675 return (int8_t) packmsg_read_hdr_(buf);
676 } else if(hdr == 0xd1) {
678 packmsg_read_data_(buf, &val, 2);
681 packmsg_input_invalidate(buf);
686 /** \brief Get an int32 value from the input.
687 * \memberof packmsg_input
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.
693 static inline int32_t packmsg_get_int32(struct packmsg_input *buf) {
694 uint8_t hdr = packmsg_read_hdr_(buf);
696 if(hdr < 0x80 || hdr >= 0xe0) {
698 } else if(hdr == 0xd0) {
699 return (int8_t) packmsg_read_hdr_(buf);
700 } else if(hdr == 0xd1) {
702 packmsg_read_data_(buf, &val, 2);
704 } else if(hdr == 0xd2) {
706 packmsg_read_data_(buf, &val, 4);
709 packmsg_input_invalidate(buf);
714 /** \brief Get an int64 value from the input.
715 * \memberof packmsg_input
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.
721 static inline int64_t packmsg_get_int64(struct packmsg_input *buf) {
722 uint8_t hdr = packmsg_read_hdr_(buf);
724 if(hdr < 0x80 || hdr >= 0xe0) {
726 } else if(hdr == 0xd0) {
727 return (int8_t) packmsg_read_hdr_(buf);
728 } else if(hdr == 0xd1) {
730 packmsg_read_data_(buf, &val, 2);
732 } else if(hdr == 0xd2) {
734 packmsg_read_data_(buf, &val, 4);
736 } else if(hdr == 0xd3) {
738 packmsg_read_data_(buf, &val, 8);
741 packmsg_input_invalidate(buf);
746 /** \brief Get an uint8 value from the input.
747 * \memberof packmsg_input
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.
753 static inline uint8_t packmsg_get_uint8(struct packmsg_input *buf) {
754 uint8_t hdr = packmsg_read_hdr_(buf);
758 } else if(hdr == 0xcc) {
759 return packmsg_read_hdr_(buf);
761 packmsg_input_invalidate(buf);
766 /** \brief Get an uint16 value from the input.
767 * \memberof packmsg_input
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.
773 static inline uint16_t packmsg_get_uint16(struct packmsg_input *buf) {
774 uint8_t hdr = packmsg_read_hdr_(buf);
778 } else if(hdr == 0xcc) {
779 return packmsg_read_hdr_(buf);
780 } else if(hdr == 0xcd) {
782 packmsg_read_data_(buf, &val, 2);
785 packmsg_input_invalidate(buf);
790 /** \brief Get an uint32 value from the input.
791 * \memberof packmsg_input
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.
797 static inline uint32_t packmsg_get_uint32(struct packmsg_input *buf) {
798 uint8_t hdr = packmsg_read_hdr_(buf);
802 } else if(hdr == 0xcc) {
803 return packmsg_read_hdr_(buf);
804 } else if(hdr == 0xcd) {
806 packmsg_read_data_(buf, &val, 2);
808 } else if(hdr == 0xce) {
810 packmsg_read_data_(buf, &val, 4);
813 packmsg_input_invalidate(buf);
818 /** \brief Get an uint64 value from the input.
819 * \memberof packmsg_input
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.
825 static inline uint64_t packmsg_get_uint64(struct packmsg_input *buf) {
826 uint8_t hdr = packmsg_read_hdr_(buf);
830 } else if(hdr == 0xcc) {
831 return packmsg_read_hdr_(buf);
832 } else if(hdr == 0xcd) {
834 packmsg_read_data_(buf, &val, 2);
836 } else if(hdr == 0xce) {
838 packmsg_read_data_(buf, &val, 4);
840 } else if(hdr == 0xcf) {
842 packmsg_read_data_(buf, &val, 8);
845 packmsg_input_invalidate(buf);
850 /** \brief Get a float value from the input.
851 * \memberof packmsg_input
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.
857 static inline float packmsg_get_float(struct packmsg_input *buf) {
858 uint8_t hdr = packmsg_read_hdr_(buf);
862 packmsg_read_data_(buf, &val, 4);
865 packmsg_input_invalidate(buf);
870 /** \brief Get a double value from the input.
871 * \memberof packmsg_input
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.
877 static inline double packmsg_get_double(struct packmsg_input *buf) {
878 uint8_t hdr = packmsg_read_hdr_(buf);
882 packmsg_read_data_(buf, &val, 8);
884 } else if(hdr == 0xca) {
886 packmsg_read_data_(buf, &val, 4);
889 packmsg_input_invalidate(buf);
894 /** \brief Get a raw pointer to a string from the input.
895 * \memberof packmsg_input
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.
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.
907 static inline uint32_t packmsg_get_str_raw(struct packmsg_input *buf, const char **str) {
910 uint8_t hdr = packmsg_read_hdr_(buf);
913 if((hdr & 0xe0) == 0xa0) {
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);
922 packmsg_input_invalidate(buf);
927 if(likely(buf->len >= slen)) {
928 *str = (const char *)buf->ptr;
933 packmsg_input_invalidate(buf);
939 /** \brief Copy a string from the input into a newly allocated buffer.
940 * \memberof packmsg_input
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().
946 * \param buf A pointer to an input buffer iterator.
948 * \return A pointer to the newly allocated buffer containing a NUL-terminated string,
949 * or NULL in case of an error.
951 static inline char *packmsg_get_str_dup(struct packmsg_input *buf) {
953 uint32_t slen = packmsg_get_str_raw(buf, &str);
955 if(likely(packmsg_input_ok(buf))) {
956 char *dup = (char *)malloc((size_t) slen + 1);
959 memcpy(dup, str, slen);
963 packmsg_input_invalidate(buf);
971 /** \brief Copy a string from the input into another buffer.
972 * \memberof packmsg_input
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).
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.
983 * \return The size of the string in bytes,
984 * or 0 in case of an error.
986 static inline uint32_t packmsg_get_str_copy(struct packmsg_input *buf, void *data, uint32_t dlen) {
990 uint32_t slen = packmsg_get_str_raw(buf, &str);
992 if(likely(packmsg_input_ok(buf))) {
993 if(likely(slen < dlen)) {
994 memcpy(data, str, slen);
995 ((char *)data)[slen] = 0;
1002 packmsg_input_invalidate(buf);
1014 /** \brief Get a raw pointer to binary data from the input.
1015 * \memberof packmsg_input
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.
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.
1027 static inline uint32_t packmsg_get_bin_raw(struct packmsg_input *buf, const void **data) {
1030 uint8_t hdr = packmsg_read_hdr_(buf);
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);
1040 packmsg_input_invalidate(buf);
1045 if(likely(buf->len >= dlen)) {
1051 packmsg_input_invalidate(buf);
1057 /** \brief Copy binary data from the input into a newly allocated buffer.
1058 * \memberof packmsg_input
1060 * This function copies binary data from the input into a buffer allocated by the library
1062 * The application is responsible for freeing the memory of the buffer using free().
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.
1067 * \return A pointer to the newly allocated buffer containing the binary data,
1068 * or NULL in case of an error.
1070 static inline void *packmsg_get_bin_dup(struct packmsg_input *buf, uint32_t *dlen) {
1072 *dlen = packmsg_get_bin_raw(buf, &data);
1074 if(likely(packmsg_input_ok(buf))) {
1075 char *dup = (char *)malloc(*dlen);
1078 memcpy(dup, data, *dlen);
1082 packmsg_input_invalidate(buf);
1090 /** \brief Copy binary data from the input into another buffer.
1091 * \memberof packmsg_input
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.
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.
1100 * \return The size of the binary data in bytes,
1101 * or 0 in case of an error.
1103 static inline uint32_t packmsg_get_bin_copy(struct packmsg_input *buf, void *rawbuf, uint32_t rlen) {
1107 uint32_t dlen = packmsg_get_bin_raw(buf, &data);
1109 if(likely(packmsg_input_ok(buf))) {
1110 if(likely(dlen <= rlen)) {
1111 memcpy(rawbuf, data, dlen);
1114 packmsg_input_invalidate(buf);
1122 /** \brief Get a raw pointer to extension data from the input.
1123 * \memberof packmsg_input
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.
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.
1136 * \return The size of the data in bytes,
1137 * or 0 in case of an error.
1139 static inline uint32_t packmsg_get_ext_raw(struct packmsg_input *buf, int8_t *type, const void **data) {
1143 uint8_t hdr = packmsg_read_hdr_(buf);
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);
1155 packmsg_input_invalidate(buf);
1161 *type = packmsg_read_hdr_(buf);
1163 if(likely(buf->len >= dlen)) {
1169 packmsg_input_invalidate(buf);
1176 /** \brief Copy extension data from the input into a newly allocated buffer.
1177 * \memberof packmsg_input
1179 * This function copies extension data from the input into a buffer allocated by the library
1181 * The application is responsible for freeing the memory of the buffer using free().
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.
1189 * \return A pointer to the newly allocated buffer containing the extension data,
1190 * or NULL in case of an error.
1192 static inline void *packmsg_get_ext_dup(struct packmsg_input *buf, int8_t *type, uint32_t *dlen) {
1196 *dlen = packmsg_get_ext_raw(buf, type, &data);
1198 if(likely(packmsg_input_ok(buf))) {
1199 char *dup = (char *)malloc(*dlen);
1202 memcpy(dup, data, *dlen);
1207 packmsg_input_invalidate(buf);
1217 /** \brief Copy extension data from the input into another buffer.
1218 * \memberof packmsg_input
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.
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.
1229 * \return The size of the extension data in bytes,
1230 * or 0 in case of an error.
1232 static inline uint32_t packmsg_get_ext_copy(struct packmsg_input *buf, int8_t *type, void *rawbuf, uint32_t rlen) {
1237 uint32_t dlen = packmsg_get_ext_raw(buf, type, &data);
1239 if(likely(packmsg_input_ok(buf))) {
1240 if(likely(dlen <= rlen)) {
1241 memcpy(rawbuf, data, dlen);
1245 packmsg_input_invalidate(buf);
1254 /** \brief Get a map header from the output.
1255 * \memberof packmsg_input
1257 * This function only reads a map header, and returns the number of key-value
1259 * These key-value pairs have to be read by the application using regular
1260 * packmsg_get_*() calls.
1262 * \param buf A pointer to an input buffer iterator.
1264 * \return The number of key-value pairs in the map.
1266 static inline uint32_t packmsg_get_map(struct packmsg_input *buf) {
1267 uint8_t hdr = packmsg_read_hdr_(buf);
1269 if((hdr & 0xf0) == 0x80) {
1271 } else if(hdr == 0xde) {
1273 packmsg_read_data_(buf, &dlen, 2);
1275 } else if(hdr == 0xdf) {
1277 packmsg_read_data_(buf, &dlen, 4);
1280 packmsg_input_invalidate(buf);
1285 /** \brief Get an array header from the output.
1286 * \memberof packmsg_input
1288 * This function only reads an array header, and returns the number of elements
1290 * These elements have to be read by the application using regular
1291 * packmsg_get_*() calls.
1293 * \param buf A pointer to an input buffer iterator.
1295 * \return The number of elements in the array.
1297 static inline uint32_t packmsg_get_array(struct packmsg_input *buf) {
1298 uint8_t hdr = packmsg_read_hdr_(buf);
1300 if((hdr & 0xf0) == 0x90) {
1302 } else if(hdr == 0xdc) {
1304 packmsg_read_data_(buf, &dlen, 2);
1306 } else if(hdr == 0xdd) {
1308 packmsg_read_data_(buf, &dlen, 4);
1311 packmsg_input_invalidate(buf);
1320 /** \brief An enum describing the type of an element in a PackMessage message.
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.
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.
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. */
1357 /** \brief Checks if the next element is a NIL.
1358 * \memberof packmsg_input
1360 * \param buf A pointer to an input buffer iterator.
1362 * \return True if the next element can be read by packmsg_get_nil(),
1363 * false if not or if any other error occurred.
1365 static inline bool packmsg_is_nil(const struct packmsg_input *buf) {
1366 return packmsg_peek_hdr_(buf) == 0xc0;
1369 /** \brief Checks if the next element is a bool.
1370 * \memberof packmsg_input
1372 * \param buf A pointer to an input buffer iterator.
1374 * \return True if the next element can be read by packmsg_get_nil(),
1375 * false if not or if any other error occurred.
1377 static inline bool packmsg_is_bool(const struct packmsg_input *buf) {
1378 return (packmsg_peek_hdr_(buf) & 0xfe) == 0xc2;
1381 /** \brief Checks if the next element is a signed integer that fits in an int8_t.
1382 * \memberof packmsg_input
1384 * \param buf A pointer to an input buffer iterator.
1386 * \return True if the next element can be read by packmsg_get_int8(),
1387 * false if not or if any other error occurred.
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;
1394 /** \brief Checks if the next element is a signed integer that fits in an int16_t.
1395 * \memberof packmsg_input
1397 * \param buf A pointer to an input buffer iterator.
1399 * \return True if the next element can be read by packmsg_get_int16(),
1400 * false if not or if any other error occurred.
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;
1407 /** \brief Checks if the next element is a signed integer that fits in an int32_t.
1408 * \memberof packmsg_input
1410 * \param buf A pointer to an input buffer iterator.
1412 * \return True if the next element can be read by packmsg_get_int32(),
1413 * false if not or if any other error occurred.
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;
1420 /** \brief Checks if the next element is a signed integer that fits in an int64_t.
1421 * \memberof packmsg_input
1423 * \param buf A pointer to an input buffer iterator.
1425 * \return True if the next element can be read by packmsg_get_int64(),
1426 * false if not or if any other error occurred.
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;
1433 /** \brief Checks if the next element is an unsigned integer that fits in an uint8_t.
1434 * \memberof packmsg_input
1436 * \param buf A pointer to an input buffer iterator.
1438 * \return True if the next element can be read by packmsg_get_uint8(),
1439 * false if not or if any other error occurred.
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;
1446 /** \brief Checks if the next element is an unsigned integer that fits in an uint16_t.
1447 * \memberof packmsg_input
1449 * \param buf A pointer to an input buffer iterator.
1451 * \return True if the next element can be read by packmsg_get_uint16(),
1452 * false if not or if any other error occurred.
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;
1459 /** \brief Checks if the next element is an unsigned integer that fits in an uint32_t.
1460 * \memberof packmsg_input
1462 * \param buf A pointer to an input buffer iterator.
1464 * \return True if the next element can be read by packmsg_get_uint32(),
1465 * false if not or if any other error occurred.
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;
1472 /** \brief Checks if the next element is an unsigned integer that fits in an uint64_t.
1473 * \memberof packmsg_input
1475 * \param buf A pointer to an input buffer iterator.
1477 * \return True if the next element can be read by packmsg_get_uint64(),
1478 * false if not or if any other error occurred.
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;
1485 /** \brief Checks if the next element is a single precision floating point value.
1486 * \memberof packmsg_input
1488 * \param buf A pointer to an input buffer iterator.
1490 * \return True if the next element can be read by packmsg_get_float(),
1491 * false if not or if any other error occurred.
1493 static inline bool packmsg_is_float(const struct packmsg_input *buf) {
1494 return packmsg_peek_hdr_(buf) == 0xca;
1497 /** \brief Checks if the next element is a single or double precision floating point value.
1498 * \memberof packmsg_input
1500 * \param buf A pointer to an input buffer iterator.
1502 * \return True if the next element can be read by packmsg_get_double(),
1503 * false if not or if any other error occurred.
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;
1510 /** \brief Checks if the next element is a string.
1511 * \memberof packmsg_input
1513 * \param buf A pointer to an input buffer iterator.
1515 * \return True if the next element can be read by packmsg_get_str_*(),
1516 * false if not or if any other error occurred.
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;
1523 /** \brief Checks if the next element is binary data.
1524 * \memberof packmsg_input
1526 * \param buf A pointer to an input buffer iterator.
1528 * \return True if the next element can be read by packmsg_get_bin_*(),
1529 * false if not or if any other error occurred.
1531 static inline bool packmsg_is_bin(const struct packmsg_input *buf) {
1532 return (packmsg_peek_hdr_(buf) & 0xfc) == 0xc4;
1535 /** \brief Checks if the next element is extension data.
1536 * \memberof packmsg_input
1538 * \param buf A pointer to an input buffer iterator.
1540 * \return True if the next element can be read by packmsg_get_ext_*(),
1541 * false if not or if any other error occurred.
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);
1548 /** \brief Checks if the next element is a map header.
1549 * \memberof packmsg_input
1551 * \param buf A pointer to an input buffer iterator.
1553 * \return True if the next element can be read by packmsg_get_map(),
1554 * false if not or if any other error occurred.
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;
1561 /** \brief Checks if the next element is an array header.
1562 * \memberof packmsg_input
1564 * \param buf A pointer to an input buffer iterator.
1566 * \return True if the next element can be read by packmsg_get_array(),
1567 * false if not or if any other error occurred.
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;
1574 /** \brief Checks the type of the next element.
1575 * \memberof packmsg_input
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.
1581 * \param buf A pointer to an output buffer iterator.
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.
1587 static inline enum packmsg_type packmsg_get_type(const struct packmsg_input *buf) {
1588 if(unlikely(packmsg_done(buf))) {
1589 return PACKMSG_DONE;
1592 uint8_t hdr = packmsg_peek_hdr_(buf);
1603 return PACKMSG_POSITIVE_FIXINT;
1609 return PACKMSG_ARRAY;
1621 return PACKMSG_ERROR;
1625 return PACKMSG_BOOL;
1638 return PACKMSG_FLOAT;
1641 return PACKMSG_DOUBLE;
1644 return PACKMSG_UINT8;
1647 return PACKMSG_UINT16;
1650 return PACKMSG_UINT32;
1653 return PACKMSG_UINT64;
1656 return PACKMSG_ERROR;
1662 return PACKMSG_INT8;
1665 return PACKMSG_INT16;
1668 return PACKMSG_INT32;
1671 return PACKMSG_INT64;
1687 return PACKMSG_ARRAY;
1694 return PACKMSG_ERROR;
1699 return PACKMSG_INT8;
1702 return PACKMSG_ERROR;
1706 /** \brief Skip one element in the input
1707 * \memberof packmsg_input
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.
1713 * \param buf A pointer to an output buffer iterator.
1715 static inline void packmsg_skip_element(struct packmsg_input *buf) {
1716 uint8_t hdr = packmsg_read_hdr_(buf);
1870 packmsg_read_data_(buf, &dlen, -skip);
1872 if(hdr >= 0xc7 && hdr <= 0xc9) {
1879 if(likely(buf->len >= dlen)) {
1883 packmsg_input_invalidate(buf);
1887 /** \brief Skip one object in the input
1888 * \memberof packmsg_input
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.
1895 * \param buf A pointer to an output buffer iterator.
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);
1901 while(count-- && buf->len >= 0) {
1902 packmsg_skip_object(buf);
1904 } else if(packmsg_is_map(buf)) {
1905 uint32_t count = packmsg_get_map(buf);
1907 while(count-- && buf->len >= 0) {
1908 packmsg_skip_object(buf);
1909 packmsg_skip_object(buf);
1912 packmsg_skip_object(buf);