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 packmsg_likely(x) __builtin_expect(!!(x), 1)
46 #define packmsg_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 packmsg_output_t variable must be initialized
73 * with a pointer to the start of an output buffer, and its size.
74 * Elements can then be encoded using packmsg_add_*() functions.
75 * When all desired elements have been added, the length of the encoded message
76 * can be retrieved using the packmsg_output_size() function.
78 * For decoding, a packmsg_input_t variable must be initialized
79 * with a const pointer to the start of an input buffer, and its size.
80 * Elements can then be decoded using packmsg_get_*() functions.
81 * If the type of elements in a message is not known up front, then
82 * the type of the next element can be queried using packmsg_get_type()
83 * or packmsg_is_*() functions. To check that the complete message has been decoded
84 * correctly, the function packmsg_done() can be called.
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 successfully, 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 packmsg_output_t *buf) {
142 return packmsg_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 packmsg_output_t *buf, const uint8_t *start) {
158 if(packmsg_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 successfully, 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 __attribute__((__warn_unused_result__)) bool packmsg_input_ok(const packmsg_input_t *buf) {
179 return packmsg_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 __attribute__((__warn_unused_result__)) bool packmsg_done(const packmsg_input_t *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(packmsg_output_t *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(packmsg_input_t *buf) {
229 /* Encoding functions
233 /** \brief Internal function, do not use. */
234 static inline void packmsg_write_hdr_(packmsg_output_t *buf, uint8_t hdr) {
238 if(packmsg_likely(buf->len > 0)) {
243 packmsg_output_invalidate(buf);
247 /** \brief Internal function, do not use. */
248 static inline void packmsg_write_data_(packmsg_output_t *buf, const void *data, uint32_t dlen) {
253 if(packmsg_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_(packmsg_output_t *buf, uint8_t hdr, const void *data, uint32_t dlen) {
268 if(packmsg_likely(buf->len > dlen)) {
273 memcpy(buf->ptr, data, dlen);
277 packmsg_output_invalidate(buf);
281 /** \brief Internal function, do not use. */
282 static inline void *packmsg_reserve_(packmsg_output_t *buf, uint32_t len) {
286 if(packmsg_likely(buf->len >= len)) {
287 void *ptr = buf->ptr;
292 packmsg_output_invalidate(buf);
297 /** \brief Add a NIL to the output.
298 * \memberof packmsg_output
300 * \param buf A pointer to an output buffer iterator.
302 static inline void packmsg_add_nil(packmsg_output_t *buf) {
303 packmsg_write_hdr_(buf, 0xc0);
306 /** \brief Add a boolean value to the output.
307 * \memberof packmsg_output
309 * \param buf A pointer to an output buffer iterator.
310 * \param val The value to add.
312 static inline void packmsg_add_bool(packmsg_output_t *buf, bool val) {
313 packmsg_write_hdr_(buf, val ? 0xc3 : 0xc2);
316 /** \brief Add an int8 value to the output.
317 * \memberof packmsg_output
319 * \param buf A pointer to an output buffer iterator.
320 * \param val The value to add.
322 static inline void packmsg_add_int8(packmsg_output_t *buf, int8_t val) {
323 if(val >= -32) { // fixint
324 packmsg_write_hdr_(buf, val);
325 } else { // TODO: negative fixint
326 packmsg_write_hdrdata_(buf, 0xd0, &val, 1);
330 /** \brief Add an int16 value to the output.
331 * \memberof packmsg_output
333 * \param buf A pointer to an output buffer iterator.
334 * \param val The value to add.
336 static inline void packmsg_add_int16(packmsg_output_t *buf, int16_t val) {
337 if((int8_t) val != val) {
338 packmsg_write_hdrdata_(buf, 0xd1, &val, 2);
340 packmsg_add_int8(buf, val);
344 /** \brief Add an int32 value to the output.
345 * \memberof packmsg_output
347 * \param buf A pointer to an output buffer iterator.
348 * \param val The value to add.
350 static inline void packmsg_add_int32(packmsg_output_t *buf, int32_t val) {
351 if((int16_t) val != val) {
352 packmsg_write_hdrdata_(buf, 0xd2, &val, 4);
354 packmsg_add_int16(buf, val);
358 /** \brief Add an int64 value to the output.
359 * \memberof packmsg_output
361 * \param buf A pointer to an output buffer iterator.
362 * \param val The value to add.
364 static inline void packmsg_add_int64(packmsg_output_t *buf, int64_t val) {
365 if((int32_t) val != val) {
366 packmsg_write_hdrdata_(buf, 0xd3, &val, 8);
368 packmsg_add_int32(buf, val);
372 /** \brief Add a uint8 value to the output.
373 * \memberof packmsg_output
375 * \param buf A pointer to an output buffer iterator.
376 * \param val The value to add.
378 static inline void packmsg_add_uint8(packmsg_output_t *buf, uint8_t val) {
379 if(val < 0x80) { // fixint
380 packmsg_write_hdr_(buf, val);
382 packmsg_write_hdrdata_(buf, 0xcc, &val, 1);
386 /** \brief Add a uint16 value to the output.
387 * \memberof packmsg_output
389 * \param buf A pointer to an output buffer iterator.
390 * \param val The value to add.
392 static inline void packmsg_add_uint16(packmsg_output_t *buf, uint16_t val) {
394 packmsg_write_hdrdata_(buf, 0xcd, &val, 2);
396 packmsg_add_uint8(buf, val);
400 /** \brief Add a int32 value to the output.
401 * \memberof packmsg_output
403 * \param buf A pointer to an output buffer iterator.
404 * \param val The value to add.
406 static inline void packmsg_add_uint32(packmsg_output_t *buf, uint32_t val) {
407 if(val & 0xffff0000) {
408 packmsg_write_hdrdata_(buf, 0xce, &val, 4);
410 packmsg_add_uint16(buf, val);
414 /** \brief Add a int64 value to the output.
415 * \memberof packmsg_output
417 * \param buf A pointer to an output buffer iterator.
418 * \param val The value to add.
420 static inline void packmsg_add_uint64(packmsg_output_t *buf, uint64_t val) {
421 if(val & 0xffffffff00000000) {
422 packmsg_write_hdrdata_(buf, 0xcf, &val, 8);
424 packmsg_add_uint32(buf, val);
428 /** \brief Add a float value to the output.
429 * \memberof packmsg_output
431 * \param buf A pointer to an output buffer iterator.
432 * \param val The value to add.
434 static inline void packmsg_add_float(packmsg_output_t *buf, float val) {
435 packmsg_write_hdrdata_(buf, 0xca, &val, 4);
438 /** \brief Add a double value to the output.
439 * \memberof packmsg_output
441 * \param buf A pointer to an output buffer iterator.
442 * \param val The value to add.
444 static inline void packmsg_add_double(packmsg_output_t *buf, double val) {
445 packmsg_write_hdrdata_(buf, 0xcb, &val, 8);
448 /** \brief Add a string with a given length to the output.
449 * \memberof packmsg_output
451 * The string must be at least as long as the given length.
452 * Any NUL-bytes within the given length range will be included.
454 * \param buf A pointer to an output buffer iterator.
455 * \param str The string to add.
456 * \param len The length of the string in bytes.
458 static inline void packmsg_add_str_raw(packmsg_output_t *buf, const char *str, uint32_t len) {
460 packmsg_write_hdr_(buf, 0xa0 | (uint8_t) len);
461 } else if(len <= 0xff) {
462 packmsg_write_hdrdata_(buf, 0xd9, &len, 1);
463 } else if(len <= 0xffff) {
464 packmsg_write_hdrdata_(buf, 0xda, &len, 2);
466 packmsg_write_hdrdata_(buf, 0xdb, &len, 4);
469 packmsg_write_data_(buf, str, len);
472 /** \brief Add a string to the output.
473 * \memberof packmsg_output
475 * \param buf A pointer to an output buffer iterator.
476 * \param str The string to add. This must be a NUL-terminated string.
478 static inline void packmsg_add_str(packmsg_output_t *buf, const char *str) {
479 size_t len = strlen(str);
481 if(packmsg_likely(len <= 0xffffffff)) {
482 packmsg_add_str_raw(buf, str, len);
484 packmsg_output_invalidate(buf);
488 /** \brief Reserve space for a string with a given length in the output.
489 * \memberof packmsg_output
491 * This writes a header for a string with the given length to the output,
492 * and reserves space for that string.
493 * The caller must fill in that space.
495 * \param buf A pointer to an output buffer iterator.
496 * \param len The length of the string in bytes.
498 * \return A pointer to the reserved space for the string,
499 * or NULL in case of an error.
501 static inline char *packmsg_add_str_reserve(packmsg_output_t *buf, uint32_t len) {
503 packmsg_write_hdr_(buf, 0xa0 | (uint8_t) len);
504 } else if(len <= 0xff) {
505 packmsg_write_hdrdata_(buf, 0xd9, &len, 1);
506 } else if(len <= 0xffff) {
507 packmsg_write_hdrdata_(buf, 0xda, &len, 2);
509 packmsg_write_hdrdata_(buf, 0xdb, &len, 4);
512 return (char *)packmsg_reserve_(buf, len);
515 /** \brief Add binary data to the output.
516 * \memberof packmsg_output
518 * \param buf A pointer to an output buffer iterator.
519 * \param data A pointer to the data to add.
520 * \param dlen The length of the data in bytes.
522 static inline void packmsg_add_bin(packmsg_output_t *buf, const void *data, uint32_t dlen) {
524 packmsg_write_hdrdata_(buf, 0xc4, &dlen, 1);
525 } else if(dlen <= 0xffff) {
526 packmsg_write_hdrdata_(buf, 0xc5, &dlen, 2);
528 packmsg_write_hdrdata_(buf, 0xc6, &dlen, 4);
531 packmsg_write_data_(buf, data, dlen);
534 /** \brief Reserve space for binary data in the output.
535 * \memberof packmsg_output
537 * This writes a header for a block of data with the given length to the output,
538 * and reserves space for that data.
539 * The caller must fill in that space.
541 * \param buf A pointer to an output buffer iterator.
542 * \param dlen The length of the data in bytes.
544 * \return A pointer to the reserved space for the data,
545 * or NULL in case of an error.
547 static inline void *packmsg_add_bin_reserve(packmsg_output_t *buf, uint32_t dlen) {
549 packmsg_write_hdrdata_(buf, 0xc4, &dlen, 1);
550 } else if(dlen <= 0xffff) {
551 packmsg_write_hdrdata_(buf, 0xc5, &dlen, 2);
553 packmsg_write_hdrdata_(buf, 0xc6, &dlen, 4);
556 return packmsg_reserve_(buf, dlen);
559 /** \brief Add extension data to the output.
560 * \memberof packmsg_output
562 * \param buf A pointer to an output buffer iterator.
563 * \param type The extension type. Values between 0 and 127 are application specific,
564 * values between -1 and -128 are reserved for future extensions.
565 * \param data A pointer to the data to add.
566 * \param dlen The length of the data in bytes.
568 static inline void packmsg_add_ext(packmsg_output_t *buf, int8_t type, const void *data, uint32_t dlen) {
571 packmsg_write_hdrdata_(buf, 0xd8, &type, 1);
572 } else if(dlen == 8) {
573 packmsg_write_hdrdata_(buf, 0xd7, &type, 1);
574 } else if(dlen == 4) {
575 packmsg_write_hdrdata_(buf, 0xd6, &type, 1);
576 } else if(dlen == 2) {
577 packmsg_write_hdrdata_(buf, 0xd5, &type, 1);
578 } else if(dlen == 1) {
579 packmsg_write_hdrdata_(buf, 0xd4, &type, 1);
581 packmsg_write_hdrdata_(buf, 0xc7, &dlen, 1);
582 packmsg_write_data_(buf, &type, 1);
584 } else if(dlen <= 0xffff) {
585 packmsg_write_hdrdata_(buf, 0xc8, &dlen, 2);
586 packmsg_write_data_(buf, &type, 1);
587 } else if(dlen <= 0xffffffff) {
588 packmsg_write_hdrdata_(buf, 0xc9, &dlen, 4);
589 packmsg_write_data_(buf, &type, 1);
591 packmsg_output_invalidate(buf);
595 packmsg_write_data_(buf, data, dlen);
598 /** \brief Reserve space for extension data in the output.
599 * \memberof packmsg_output
601 * This writes a header for extension data with the given type
602 * and length to the output,
603 * and reserves space for that extension data.
604 * The caller must fill in that space.
606 * \param buf A pointer to an output buffer iterator.
607 * \param type The extension type. Values between 0 and 127 are application specific,
608 * values between -1 and -128 are reserved for future extensions.
609 * \param dlen The length of the data in bytes.
611 * \return A pointer to the reserved space for the extension data,
612 * or NULL in case of an error.
614 static inline void *packmsg_add_ext_reserve(packmsg_output_t *buf, int8_t type, uint32_t dlen) {
617 packmsg_write_hdrdata_(buf, 0xd8, &type, 1);
618 } else if(dlen == 8) {
619 packmsg_write_hdrdata_(buf, 0xd7, &type, 1);
620 } else if(dlen == 4) {
621 packmsg_write_hdrdata_(buf, 0xd6, &type, 1);
622 } else if(dlen == 2) {
623 packmsg_write_hdrdata_(buf, 0xd5, &type, 1);
624 } else if(dlen == 1) {
625 packmsg_write_hdrdata_(buf, 0xd4, &type, 1);
627 packmsg_write_hdrdata_(buf, 0xc7, &dlen, 1);
628 packmsg_write_data_(buf, &type, 1);
630 } else if(dlen <= 0xffff) {
631 packmsg_write_hdrdata_(buf, 0xc8, &dlen, 2);
632 packmsg_write_data_(buf, &type, 1);
634 packmsg_write_hdrdata_(buf, 0xc9, &dlen, 4);
635 packmsg_write_data_(buf, &type, 1);
638 return packmsg_reserve_(buf, dlen);
641 /** \brief Add a map header to the output.
642 * \memberof packmsg_output
644 * This function only adds an an indicator that the next 2 * count elements
645 * are a sequence of key-value pairs that make up the contents of the map.
646 * These key-value pairs have to be added by the application using regular
647 * packmsg_add_*() calls.
649 * \param buf A pointer to an output buffer iterator.
650 * \param count The number of elements in the map.
652 static inline void packmsg_add_map(packmsg_output_t *buf, uint32_t count) {
654 packmsg_write_hdr_(buf, 0x80 | (uint8_t) count);
655 } else if(count <= 0xffff) {
656 packmsg_write_hdrdata_(buf, 0xde, &count, 2);
658 packmsg_write_hdrdata_(buf, 0xdf, &count, 4);
662 /** \brief Add an array header to the output.
663 * \memberof packmsg_output
665 * This function only adds an an indicator that the next count elements
666 * are a sequence of elements that make up the contents of the array.
667 * These elements have to be added by the application using regular
668 * packmsg_add_*() calls.
670 * \param buf A pointer to an output buffer iterator.
671 * \param count The number of elements in the array.
673 static inline void packmsg_add_array(packmsg_output_t *buf, uint32_t count) {
675 packmsg_write_hdr_(buf, 0x90 | (uint8_t) count);
676 } else if(count <= 0xffff) {
677 packmsg_write_hdrdata_(buf, 0xdc, &count, 2);
679 packmsg_write_hdrdata_(buf, 0xdd, &count, 4);
683 /* Decoding functions
687 /** \brief Internal function, do not use. */
688 static inline uint8_t packmsg_read_hdr_(packmsg_input_t *buf) {
692 if(packmsg_likely(buf->len > 0)) {
693 uint8_t hdr = *buf->ptr;
698 packmsg_input_invalidate(buf);
703 /** \brief Internal function, do not use. */
704 static inline void packmsg_read_data_(packmsg_input_t *buf, void *data, uint32_t dlen) {
709 if(packmsg_likely(buf->len >= dlen)) {
710 memcpy(data, buf->ptr, dlen);
714 packmsg_input_invalidate(buf);
718 /** \brief Internal function, do not use. */
719 static inline uint8_t packmsg_peek_hdr_(const packmsg_input_t *buf) {
723 if(packmsg_likely(buf->len > 0)) {
730 /** \brief Get a NIL from the input.
731 * \memberof packmsg_input
733 * This function does not return anything, but will invalidate the input iterator
734 * if no NIL was successfully consumed from the input.
736 * \param buf A pointer to an input buffer iterator.
738 static inline void packmsg_get_nil(packmsg_input_t *buf) {
739 if(packmsg_read_hdr_(buf) != 0xc0) {
740 packmsg_input_invalidate(buf);
745 /** \brief Get a boolean value from the input.
746 * \memberof packmsg_input
748 * \param buf A pointer to an input buffer iterator.
749 * \return The boolean value that was read from the input,
750 * or false in case of an error.
752 static inline bool packmsg_get_bool(packmsg_input_t *buf) {
753 uint8_t hdr = packmsg_read_hdr_(buf);
757 } else if(hdr == 0xc3) {
760 packmsg_input_invalidate(buf);
765 /** \brief Get an int8 value from the input.
766 * \memberof packmsg_input
768 * \param buf A pointer to an input buffer iterator.
769 * \return The int8 value that was read from the input,
770 * or 0 in case of an error.
772 static inline int8_t packmsg_get_int8(packmsg_input_t *buf) {
773 uint8_t hdr = packmsg_read_hdr_(buf);
775 if(hdr < 0x80 || hdr >= 0xe0) {
777 } else if(hdr == 0xd0) {
778 return packmsg_read_hdr_(buf);
780 packmsg_input_invalidate(buf);
785 /** \brief Get an int16 value from the input.
786 * \memberof packmsg_input
788 * \param buf A pointer to an input buffer iterator.
789 * \return The int16 value that was read from the input,
790 * or 0 in case of an error.
792 static inline int16_t packmsg_get_int16(packmsg_input_t *buf) {
793 uint8_t hdr = packmsg_read_hdr_(buf);
795 if(hdr < 0x80 || hdr >= 0xe0) {
797 } else if(hdr == 0xd0) {
798 return (int8_t) packmsg_read_hdr_(buf);
799 } else if(hdr == 0xd1) {
801 packmsg_read_data_(buf, &val, 2);
804 packmsg_input_invalidate(buf);
809 /** \brief Get an int32 value from the input.
810 * \memberof packmsg_input
812 * \param buf A pointer to an input buffer iterator.
813 * \return The int32 value that was read from the input,
814 * or 0 in case of an error.
816 static inline int32_t packmsg_get_int32(packmsg_input_t *buf) {
817 uint8_t hdr = packmsg_read_hdr_(buf);
819 if(hdr < 0x80 || hdr >= 0xe0) {
821 } else if(hdr == 0xd0) {
822 return (int8_t) packmsg_read_hdr_(buf);
823 } else if(hdr == 0xd1) {
825 packmsg_read_data_(buf, &val, 2);
827 } else if(hdr == 0xd2) {
829 packmsg_read_data_(buf, &val, 4);
832 packmsg_input_invalidate(buf);
837 /** \brief Get an int64 value from the input.
838 * \memberof packmsg_input
840 * \param buf A pointer to an input buffer iterator.
841 * \return The int64 value that was read from the input,
842 * or 0 in case of an error.
844 static inline int64_t packmsg_get_int64(packmsg_input_t *buf) {
845 uint8_t hdr = packmsg_read_hdr_(buf);
847 if(hdr < 0x80 || hdr >= 0xe0) {
849 } else if(hdr == 0xd0) {
850 return (int8_t) packmsg_read_hdr_(buf);
851 } else if(hdr == 0xd1) {
853 packmsg_read_data_(buf, &val, 2);
855 } else if(hdr == 0xd2) {
857 packmsg_read_data_(buf, &val, 4);
859 } else if(hdr == 0xd3) {
861 packmsg_read_data_(buf, &val, 8);
864 packmsg_input_invalidate(buf);
869 /** \brief Get an uint8 value from the input.
870 * \memberof packmsg_input
872 * \param buf A pointer to an input buffer iterator.
873 * \return The uint8 value that was read from the input,
874 * or 0 in case of an error.
876 static inline uint8_t packmsg_get_uint8(packmsg_input_t *buf) {
877 uint8_t hdr = packmsg_read_hdr_(buf);
881 } else if(hdr == 0xcc) {
882 return packmsg_read_hdr_(buf);
884 packmsg_input_invalidate(buf);
889 /** \brief Get an uint16 value from the input.
890 * \memberof packmsg_input
892 * \param buf A pointer to an input buffer iterator.
893 * \return The uint16 value that was read from the input,
894 * or 0 in case of an error.
896 static inline uint16_t packmsg_get_uint16(packmsg_input_t *buf) {
897 uint8_t hdr = packmsg_read_hdr_(buf);
901 } else if(hdr == 0xcc) {
902 return packmsg_read_hdr_(buf);
903 } else if(hdr == 0xcd) {
905 packmsg_read_data_(buf, &val, 2);
908 packmsg_input_invalidate(buf);
913 /** \brief Get an uint32 value from the input.
914 * \memberof packmsg_input
916 * \param buf A pointer to an input buffer iterator.
917 * \return The uint32 value that was read from the input,
918 * or 0 in case of an error.
920 static inline uint32_t packmsg_get_uint32(packmsg_input_t *buf) {
921 uint8_t hdr = packmsg_read_hdr_(buf);
925 } else if(hdr == 0xcc) {
926 return packmsg_read_hdr_(buf);
927 } else if(hdr == 0xcd) {
929 packmsg_read_data_(buf, &val, 2);
931 } else if(hdr == 0xce) {
933 packmsg_read_data_(buf, &val, 4);
936 packmsg_input_invalidate(buf);
941 /** \brief Get an uint64 value from the input.
942 * \memberof packmsg_input
944 * \param buf A pointer to an input buffer iterator.
945 * \return The uint64 value that was read from the input,
946 * or 0 in case of an error.
948 static inline uint64_t packmsg_get_uint64(packmsg_input_t *buf) {
949 uint8_t hdr = packmsg_read_hdr_(buf);
953 } else if(hdr == 0xcc) {
954 return packmsg_read_hdr_(buf);
955 } else if(hdr == 0xcd) {
957 packmsg_read_data_(buf, &val, 2);
959 } else if(hdr == 0xce) {
961 packmsg_read_data_(buf, &val, 4);
963 } else if(hdr == 0xcf) {
965 packmsg_read_data_(buf, &val, 8);
968 packmsg_input_invalidate(buf);
973 /** \brief Get a float value from the input.
974 * \memberof packmsg_input
976 * \param buf A pointer to an input buffer iterator.
977 * \return The float value that was read from the input,
978 * or 0 in case of an error.
980 static inline float packmsg_get_float(packmsg_input_t *buf) {
981 uint8_t hdr = packmsg_read_hdr_(buf);
985 packmsg_read_data_(buf, &val, 4);
988 packmsg_input_invalidate(buf);
993 /** \brief Get a double value from the input.
994 * \memberof packmsg_input
996 * \param buf A pointer to an input buffer iterator.
997 * \return The float value that was read from the input,
998 * or 0 in case of an error.
1000 static inline double packmsg_get_double(packmsg_input_t *buf) {
1001 uint8_t hdr = packmsg_read_hdr_(buf);
1005 packmsg_read_data_(buf, &val, 8);
1007 } else if(hdr == 0xca) {
1009 packmsg_read_data_(buf, &val, 4);
1012 packmsg_input_invalidate(buf);
1017 /** \brief Get a raw pointer to a string from the input.
1018 * \memberof packmsg_input
1020 * This function returns the size of a string and a pointer into the input buffer itself,
1021 * to a string that is *not NUL-terminated!* This function avoids making a copy of the string,
1022 * but the application must take care to not read more than the returned number of bytes.
1024 * \param buf A pointer to an input buffer iterator.
1025 * \param[out] str A pointer to a const char pointer that will be set to the start of the string,
1026 * or will be set to NULL in case of an error.
1027 * \return The size of the string in bytes,
1028 * or 0 in case of an error.
1030 static inline uint32_t packmsg_get_str_raw(packmsg_input_t *buf, const char **str) {
1033 uint8_t hdr = packmsg_read_hdr_(buf);
1036 if((hdr & 0xe0) == 0xa0) {
1038 } else if(hdr == 0xd9) {
1039 packmsg_read_data_(buf, &slen, 1);
1040 } else if(hdr == 0xda) {
1041 packmsg_read_data_(buf, &slen, 2);
1042 } else if(hdr == 0xdb) {
1043 packmsg_read_data_(buf, &slen, 4);
1045 packmsg_input_invalidate(buf);
1050 if(packmsg_likely(buf->len >= slen)) {
1051 *str = (const char *)buf->ptr;
1056 packmsg_input_invalidate(buf);
1062 /** \brief Copy a string from the input into a newly allocated buffer.
1063 * \memberof packmsg_input
1065 * This function copies a string from the input into a buffer allocated by the library
1066 * using malloc(). The copy will be NUL-terminated.
1067 * The application is responsible for freeing the memory of the buffer using free().
1069 * \param buf A pointer to an input buffer iterator.
1071 * \return A pointer to the newly allocated buffer containing a NUL-terminated string,
1072 * or NULL in case of an error.
1074 static inline char *packmsg_get_str_dup(packmsg_input_t *buf) {
1076 uint32_t slen = packmsg_get_str_raw(buf, &str);
1078 if(packmsg_likely(packmsg_input_ok(buf))) {
1079 char *dup = (char *)malloc((size_t) slen + 1);
1081 if(packmsg_likely(dup)) {
1082 memcpy(dup, str, slen);
1086 packmsg_input_invalidate(buf);
1094 /** \brief Copy a string from the input into another buffer.
1095 * \memberof packmsg_input
1097 * This function copies a string from the input another buffer provided by the application.
1098 * The buffer must be long enough to hold the complete string plus a terminating NUL-byte.
1099 * If the buffer is not long enough, or another error occurred,
1100 * a single NUL-byte will be written to the start of the buffer (if its size is at least one byte).
1102 * \param buf A pointer to an input buffer iterator.
1103 * \param data A pointer to a buffer allocated by the application.
1104 * \param dlen The size of the buffer pointed to by data.
1106 * \return The size of the string in bytes,
1107 * or 0 in case of an error.
1109 static inline uint32_t packmsg_get_str_copy(packmsg_input_t *buf, void *data, uint32_t dlen) {
1113 uint32_t slen = packmsg_get_str_raw(buf, &str);
1115 if(packmsg_likely(packmsg_input_ok(buf))) {
1116 if(packmsg_likely(slen < dlen)) {
1117 memcpy(data, str, slen);
1118 ((char *)data)[slen] = 0;
1125 packmsg_input_invalidate(buf);
1137 /** \brief Get a raw pointer to binary data from the input.
1138 * \memberof packmsg_input
1140 * This function returns the size of the binary data and a pointer into the input buffer itself.
1141 * This function avoids making a copy of the binary data,
1142 * but the application must take care to not read more than the returned number of bytes.
1144 * \param buf A pointer to an input buffer iterator.
1145 * \param[out] data A pointer to a const void pointer that will be set to the start of the data,
1146 * or will be set to NULL in case of an error.
1147 * \return The size of the data in bytes,
1148 * or 0 in case of an error.
1150 static inline uint32_t packmsg_get_bin_raw(packmsg_input_t *buf, const void **data) {
1153 uint8_t hdr = packmsg_read_hdr_(buf);
1157 packmsg_read_data_(buf, &dlen, 1);
1158 } else if(hdr == 0xc5) {
1159 packmsg_read_data_(buf, &dlen, 2);
1160 } else if(hdr == 0xc6) {
1161 packmsg_read_data_(buf, &dlen, 4);
1163 packmsg_input_invalidate(buf);
1168 if(packmsg_likely(buf->len >= dlen)) {
1174 packmsg_input_invalidate(buf);
1180 /** \brief Copy binary data from the input into a newly allocated buffer.
1181 * \memberof packmsg_input
1183 * This function copies binary data from the input into a buffer allocated by the library
1185 * The application is responsible for freeing the memory of the buffer using free().
1187 * \param buf A pointer to an input buffer iterator.
1188 * \param[out] dlen A pointer to an uint32_t that will be set to the size of the binary data.
1190 * \return A pointer to the newly allocated buffer containing the binary data,
1191 * or NULL in case of an error.
1193 static inline void *packmsg_get_bin_dup(packmsg_input_t *buf, uint32_t *dlen) {
1195 *dlen = packmsg_get_bin_raw(buf, &data);
1197 if(packmsg_likely(packmsg_input_ok(buf))) {
1198 char *dup = (char *)malloc(*dlen);
1200 if(packmsg_likely(dup)) {
1201 memcpy(dup, data, *dlen);
1205 packmsg_input_invalidate(buf);
1213 /** \brief Copy binary data from the input into another buffer.
1214 * \memberof packmsg_input
1216 * This function copies binary data from the input another buffer provided by the application.
1217 * The buffer must be long enough to hold all the binary data.
1219 * \param buf A pointer to an input buffer iterator.
1220 * \param rawbuf A pointer to a buffer allocated by the application.
1221 * \param rlen The size of the buffer pointed to by data.
1223 * \return The size of the binary data in bytes,
1224 * or 0 in case of an error.
1226 static inline uint32_t packmsg_get_bin_copy(packmsg_input_t *buf, void *rawbuf, uint32_t rlen) {
1230 uint32_t dlen = packmsg_get_bin_raw(buf, &data);
1232 if(packmsg_likely(packmsg_input_ok(buf))) {
1233 if(packmsg_likely(dlen <= rlen)) {
1234 memcpy(rawbuf, data, dlen);
1237 packmsg_input_invalidate(buf);
1245 /** \brief Get a raw pointer to extension data from the input.
1246 * \memberof packmsg_input
1248 * This function returns the type of the extension, the size of the data
1249 * and a pointer into the input buffer itself.
1250 * This function avoids making a copy of the binary data,
1251 * but the application must take care to not read more than the returned number of bytes.
1253 * \param buf A pointer to an input buffer iterator.
1254 * \param[out] type A pointer to an int8_t that will be set to the type of the extension.
1255 * or will be set to 0 in case of an error.
1256 * \param[out] data A pointer to a const void pointer that will be set to the start of the data,
1257 * or will be set to NULL in case of an error.
1259 * \return The size of the data in bytes,
1260 * or 0 in case of an error.
1262 static inline uint32_t packmsg_get_ext_raw(packmsg_input_t *buf, int8_t *type, const void **data) {
1266 uint8_t hdr = packmsg_read_hdr_(buf);
1270 packmsg_read_data_(buf, &dlen, 1);
1271 } else if(hdr == 0xc8) {
1272 packmsg_read_data_(buf, &dlen, 2);
1273 } else if(hdr == 0xc9) {
1274 packmsg_read_data_(buf, &dlen, 4);
1275 } else if(hdr >= 0xd4 && hdr <= 0xd8) {
1276 dlen = 1 << (hdr - 0xd4);
1278 packmsg_input_invalidate(buf);
1284 *type = packmsg_read_hdr_(buf);
1286 if(packmsg_likely(buf->len >= dlen)) {
1292 packmsg_input_invalidate(buf);
1299 /** \brief Copy extension data from the input into a newly allocated buffer.
1300 * \memberof packmsg_input
1302 * This function copies extension data from the input into a buffer allocated by the library
1304 * The application is responsible for freeing the memory of the buffer using free().
1306 * \param buf A pointer to an input buffer iterator.
1307 * \param[out] type A pointer to an int8_t that will be set to the type of the extension.
1308 * or will be set to 0 in case of an error.
1309 * \param[out] dlen A pointer to an uint32_t that will be set to the size of the extension data,
1310 * or will be set to 0 in case of an error.
1312 * \return A pointer to the newly allocated buffer containing the extension data,
1313 * or NULL in case of an error.
1315 static inline void *packmsg_get_ext_dup(packmsg_input_t *buf, int8_t *type, uint32_t *dlen) {
1319 *dlen = packmsg_get_ext_raw(buf, type, &data);
1321 if(packmsg_likely(packmsg_input_ok(buf))) {
1322 char *dup = (char *)malloc(*dlen);
1324 if(packmsg_likely(dup)) {
1325 memcpy(dup, data, *dlen);
1330 packmsg_input_invalidate(buf);
1340 /** \brief Copy extension data from the input into another buffer.
1341 * \memberof packmsg_input
1343 * This function copies extension data from the input another buffer provided by the application.
1344 * The buffer must be long enough to hold all the extension data.
1346 * \param buf A pointer to an input buffer iterator.
1347 * \param[out] type A pointer to an int8_t that will be set to the type of the extension.
1348 * or will be set to 0 in case of an error.
1349 * \param rawbuf A pointer to a buffer allocated by the application.
1350 * \param rlen The size of the buffer pointed to by data.
1352 * \return The size of the extension data in bytes,
1353 * or 0 in case of an error.
1355 static inline uint32_t packmsg_get_ext_copy(packmsg_input_t *buf, int8_t *type, void *rawbuf, uint32_t rlen) {
1360 uint32_t dlen = packmsg_get_ext_raw(buf, type, &data);
1362 if(packmsg_likely(packmsg_input_ok(buf))) {
1363 if(packmsg_likely(dlen <= rlen)) {
1364 memcpy(rawbuf, data, dlen);
1368 packmsg_input_invalidate(buf);
1377 /** \brief Get a map header from the output.
1378 * \memberof packmsg_input
1380 * This function only reads a map header, and returns the number of key-value
1382 * These key-value pairs have to be read by the application using regular
1383 * packmsg_get_*() calls.
1385 * \param buf A pointer to an input buffer iterator.
1387 * \return The number of key-value pairs in the map.
1389 static inline uint32_t packmsg_get_map(packmsg_input_t *buf) {
1390 uint8_t hdr = packmsg_read_hdr_(buf);
1392 if((hdr & 0xf0) == 0x80) {
1394 } else if(hdr == 0xde) {
1396 packmsg_read_data_(buf, &dlen, 2);
1398 } else if(hdr == 0xdf) {
1400 packmsg_read_data_(buf, &dlen, 4);
1403 packmsg_input_invalidate(buf);
1408 /** \brief Get an array header from the output.
1409 * \memberof packmsg_input
1411 * This function only reads an array header, and returns the number of elements
1413 * These elements have to be read by the application using regular
1414 * packmsg_get_*() calls.
1416 * \param buf A pointer to an input buffer iterator.
1418 * \return The number of elements in the array.
1420 static inline uint32_t packmsg_get_array(packmsg_input_t *buf) {
1421 uint8_t hdr = packmsg_read_hdr_(buf);
1423 if((hdr & 0xf0) == 0x90) {
1425 } else if(hdr == 0xdc) {
1427 packmsg_read_data_(buf, &dlen, 2);
1429 } else if(hdr == 0xdd) {
1431 packmsg_read_data_(buf, &dlen, 4);
1434 packmsg_input_invalidate(buf);
1443 /** \brief An enum describing the type of an element in a PackMessage message.
1445 * This enum describes the type of an element in a PackMessage message.
1446 * In case of integers and floating point values, the type normally represents
1447 * the smallest type that can successfully hold the value of the element;
1448 * i.e. an element of type PACKMSG_INT32 can only successfully be read by
1449 * packmsg_get_int32() or packmsg_get_int64(). However, the converse it not true;
1450 * for an element of type PACKMSG_INT32, there is no guarantee
1451 * that the value is larger than would fit into an int16_t.
1453 * PackMessage makes a clear distinction between signed and unsigned integers,
1454 * except in the case of positive fixints (values between 0 and 127 inclusive),
1455 * which can be read as both signed and unsigned.
1458 PACKMSG_ERROR, /**< An invalid element was found or the input buffer is in an invalid state. */
1459 PACKMSG_NIL, /**< The next element is a NIL. */
1460 PACKMSG_BOOL, /**< The next element is a boolean. */
1461 PACKMSG_POSITIVE_FIXINT, /**< The next element is an integer between 0 and 127 inclusive. */
1462 PACKMSG_INT8, /**< The next element is a signed integer that fits in an int8_t. */
1463 PACKMSG_INT16, /**< The next element is a signed integer that fits in an int16_t. */
1464 PACKMSG_INT32, /**< The next element is a signed integer that fits in an int32_t. */
1465 PACKMSG_INT64, /**< The next element is a signed integer that fits in an int64_t. */
1466 PACKMSG_UINT8, /**< The next element is an unsigned integer that fits in an uint8_t. */
1467 PACKMSG_UINT16, /**< The next element is an unsigned integer that fits in an uint16_t. */
1468 PACKMSG_UINT32, /**< The next element is an unsigned integer that fits in an uint32_t. */
1469 PACKMSG_UINT64, /**< The next element is an unsigned integer that fits in an uint64_t. */
1470 PACKMSG_FLOAT, /**< The next element is a single precision floating point value. */
1471 PACKMSG_DOUBLE, /**< The next element is a double precision floating point value. */
1472 PACKMSG_STR, /**< The next element is a string. */
1473 PACKMSG_BIN, /**< The next element is binary data. */
1474 PACKMSG_EXT, /**< The next element is extension data. */
1475 PACKMSG_MAP, /**< The next element is a map header. */
1476 PACKMSG_ARRAY, /**< The next element is an array header. */
1477 PACKMSG_DONE, /**< There are no more elements in the input buffer. */
1480 /** \brief Checks if the next element is a NIL.
1481 * \memberof packmsg_input
1483 * \param buf A pointer to an input buffer iterator.
1485 * \return True if the next element can be read by packmsg_get_nil(),
1486 * false if not or if any other error occurred.
1488 static inline bool packmsg_is_nil(const packmsg_input_t *buf) {
1489 return packmsg_peek_hdr_(buf) == 0xc0;
1492 /** \brief Checks if the next element is a bool.
1493 * \memberof packmsg_input
1495 * \param buf A pointer to an input buffer iterator.
1497 * \return True if the next element can be read by packmsg_get_nil(),
1498 * false if not or if any other error occurred.
1500 static inline bool packmsg_is_bool(const packmsg_input_t *buf) {
1501 return (packmsg_peek_hdr_(buf) & 0xfe) == 0xc2;
1504 /** \brief Checks if the next element is a signed integer that fits in an int8_t.
1505 * \memberof packmsg_input
1507 * \param buf A pointer to an input buffer iterator.
1509 * \return True if the next element can be read by packmsg_get_int8(),
1510 * false if not or if any other error occurred.
1512 static inline bool packmsg_is_int8(const packmsg_input_t *buf) {
1513 uint8_t hdr = packmsg_peek_hdr_(buf);
1514 return hdr < 0x80 || hdr == 0xd0;
1517 /** \brief Checks if the next element is a signed integer that fits in an int16_t.
1518 * \memberof packmsg_input
1520 * \param buf A pointer to an input buffer iterator.
1522 * \return True if the next element can be read by packmsg_get_int16(),
1523 * false if not or if any other error occurred.
1525 static inline bool packmsg_is_int16(const packmsg_input_t *buf) {
1526 uint8_t hdr = packmsg_peek_hdr_(buf);
1527 return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1;
1530 /** \brief Checks if the next element is a signed integer that fits in an int32_t.
1531 * \memberof packmsg_input
1533 * \param buf A pointer to an input buffer iterator.
1535 * \return True if the next element can be read by packmsg_get_int32(),
1536 * false if not or if any other error occurred.
1538 static inline bool packmsg_is_int32(const packmsg_input_t *buf) {
1539 uint8_t hdr = packmsg_peek_hdr_(buf);
1540 return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1 || hdr == 0xd2;
1543 /** \brief Checks if the next element is a signed integer that fits in an int64_t.
1544 * \memberof packmsg_input
1546 * \param buf A pointer to an input buffer iterator.
1548 * \return True if the next element can be read by packmsg_get_int64(),
1549 * false if not or if any other error occurred.
1551 static inline bool packmsg_is_int64(const packmsg_input_t *buf) {
1552 uint8_t hdr = packmsg_peek_hdr_(buf);
1553 return hdr < 0x80 || hdr == 0xd0 || hdr == 0xd1 || hdr == 0xd2 || hdr == 0xd3;
1556 /** \brief Checks if the next element is an unsigned integer that fits in an uint8_t.
1557 * \memberof packmsg_input
1559 * \param buf A pointer to an input buffer iterator.
1561 * \return True if the next element can be read by packmsg_get_uint8(),
1562 * false if not or if any other error occurred.
1564 static inline bool packmsg_is_uint8(const packmsg_input_t *buf) {
1565 uint8_t hdr = packmsg_peek_hdr_(buf);
1566 return hdr < 0x80 || hdr == 0xcc;
1569 /** \brief Checks if the next element is an unsigned integer that fits in an uint16_t.
1570 * \memberof packmsg_input
1572 * \param buf A pointer to an input buffer iterator.
1574 * \return True if the next element can be read by packmsg_get_uint16(),
1575 * false if not or if any other error occurred.
1577 static inline bool packmsg_is_uint16(const packmsg_input_t *buf) {
1578 uint8_t hdr = packmsg_peek_hdr_(buf);
1579 return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd;
1582 /** \brief Checks if the next element is an unsigned integer that fits in an uint32_t.
1583 * \memberof packmsg_input
1585 * \param buf A pointer to an input buffer iterator.
1587 * \return True if the next element can be read by packmsg_get_uint32(),
1588 * false if not or if any other error occurred.
1590 static inline bool packmsg_is_uint32(const packmsg_input_t *buf) {
1591 uint8_t hdr = packmsg_peek_hdr_(buf);
1592 return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd || hdr == 0xce;
1595 /** \brief Checks if the next element is an unsigned integer that fits in an uint64_t.
1596 * \memberof packmsg_input
1598 * \param buf A pointer to an input buffer iterator.
1600 * \return True if the next element can be read by packmsg_get_uint64(),
1601 * false if not or if any other error occurred.
1603 static inline bool packmsg_is_uint64(const packmsg_input_t *buf) {
1604 uint8_t hdr = packmsg_peek_hdr_(buf);
1605 return hdr < 0x80 || hdr == 0xcc || hdr == 0xcd || hdr == 0xce || hdr == 0xcf;
1608 /** \brief Checks if the next element is a single precision floating point value.
1609 * \memberof packmsg_input
1611 * \param buf A pointer to an input buffer iterator.
1613 * \return True if the next element can be read by packmsg_get_float(),
1614 * false if not or if any other error occurred.
1616 static inline bool packmsg_is_float(const packmsg_input_t *buf) {
1617 return packmsg_peek_hdr_(buf) == 0xca;
1620 /** \brief Checks if the next element is a single or double precision floating point value.
1621 * \memberof packmsg_input
1623 * \param buf A pointer to an input buffer iterator.
1625 * \return True if the next element can be read by packmsg_get_double(),
1626 * false if not or if any other error occurred.
1628 static inline bool packmsg_is_double(const packmsg_input_t *buf) {
1629 uint8_t hdr = packmsg_peek_hdr_(buf);
1630 return hdr == 0xcb || hdr == 0xca;
1633 /** \brief Checks if the next element is a string.
1634 * \memberof packmsg_input
1636 * \param buf A pointer to an input buffer iterator.
1638 * \return True if the next element can be read by packmsg_get_str_*(),
1639 * false if not or if any other error occurred.
1641 static inline bool packmsg_is_str(const packmsg_input_t *buf) {
1642 uint8_t hdr = packmsg_peek_hdr_(buf);
1643 return (hdr & 0xe0) == 0xa0 || hdr == 0xd9 || hdr == 0xda || hdr == 0xdb;
1646 /** \brief Checks if the next element is binary data.
1647 * \memberof packmsg_input
1649 * \param buf A pointer to an input buffer iterator.
1651 * \return True if the next element can be read by packmsg_get_bin_*(),
1652 * false if not or if any other error occurred.
1654 static inline bool packmsg_is_bin(const packmsg_input_t *buf) {
1655 return (packmsg_peek_hdr_(buf) & 0xfc) == 0xc4;
1658 /** \brief Checks if the next element is extension data.
1659 * \memberof packmsg_input
1661 * \param buf A pointer to an input buffer iterator.
1663 * \return True if the next element can be read by packmsg_get_ext_*(),
1664 * false if not or if any other error occurred.
1666 static inline bool packmsg_is_ext(const packmsg_input_t *buf) {
1667 uint8_t hdr = packmsg_peek_hdr_(buf);
1668 return (hdr >= 0xc7 && hdr <= 0xc9) || (hdr >= 0xd4 && hdr <= 0xd8);
1671 /** \brief Checks if the next element is a map header.
1672 * \memberof packmsg_input
1674 * \param buf A pointer to an input buffer iterator.
1676 * \return True if the next element can be read by packmsg_get_map(),
1677 * false if not or if any other error occurred.
1679 static inline bool packmsg_is_map(const packmsg_input_t *buf) {
1680 uint8_t hdr = packmsg_peek_hdr_(buf);
1681 return (hdr & 0xf0) == 0x80 || hdr == 0xde || hdr == 0xdf;
1684 /** \brief Checks if the next element is an array header.
1685 * \memberof packmsg_input
1687 * \param buf A pointer to an input buffer iterator.
1689 * \return True if the next element can be read by packmsg_get_array(),
1690 * false if not or if any other error occurred.
1692 static inline bool packmsg_is_array(const packmsg_input_t *buf) {
1693 uint8_t hdr = packmsg_peek_hdr_(buf);
1694 return (hdr & 0xf0) == 0x90 || hdr == 0xdc || hdr == 0xdd;
1697 /** \brief Checks the type of the next element.
1698 * \memberof packmsg_input
1700 * This function checks the next element and returns an enum packmsg_type
1701 * that describes the type of the element. If the input buffer was fully consumed
1702 * and there are no more elements left, this function will return PACKMSG_DONE.
1704 * \param buf A pointer to an output buffer iterator.
1706 * \return The type of the next element, or PACKMSG_DONE if no more elements
1707 * are present in the input buffer, or PACKMSG_ERROR if the next element
1708 * is invalid, or if any other error occurred.
1710 static inline enum packmsg_type packmsg_get_type(const packmsg_input_t *buf) {
1711 if(packmsg_unlikely(packmsg_done(buf))) {
1712 return PACKMSG_DONE;
1715 uint8_t hdr = packmsg_peek_hdr_(buf);
1726 return PACKMSG_POSITIVE_FIXINT;
1732 return PACKMSG_ARRAY;
1744 return PACKMSG_ERROR;
1748 return PACKMSG_BOOL;
1761 return PACKMSG_FLOAT;
1764 return PACKMSG_DOUBLE;
1767 return PACKMSG_UINT8;
1770 return PACKMSG_UINT16;
1773 return PACKMSG_UINT32;
1776 return PACKMSG_UINT64;
1779 return PACKMSG_ERROR;
1785 return PACKMSG_INT8;
1788 return PACKMSG_INT16;
1791 return PACKMSG_INT32;
1794 return PACKMSG_INT64;
1810 return PACKMSG_ARRAY;
1817 return PACKMSG_ERROR;
1822 return PACKMSG_INT8;
1825 return PACKMSG_ERROR;
1829 /** \brief Skip one element in the input
1830 * \memberof packmsg_input
1832 * This function skips the next element in the input.
1833 * If the element is a map or an array, only the map or array header is skipped,
1834 * but not the contents of the map or array.
1836 * \param buf A pointer to an output buffer iterator.
1838 static inline void packmsg_skip_element(packmsg_input_t *buf) {
1839 uint8_t hdr = packmsg_read_hdr_(buf);
1996 packmsg_read_data_(buf, &dlen, -skip);
1998 if(hdr >= 0xc7 && hdr <= 0xc9) {
2005 if(packmsg_likely(buf->len >= dlen)) {
2009 packmsg_input_invalidate(buf);
2013 /** \brief Skip one object in the input
2014 * \memberof packmsg_input
2016 * This function checks the type of the next element.
2017 * In case it is a scalar value (for example, an int or a string),
2018 * it skips just that scalar. If the next element is a map or an array,
2019 * it will recursively skip as many objects as there are in that map or array.
2021 * \param buf A pointer to an output buffer iterator.
2023 static inline void packmsg_skip_object(packmsg_input_t *buf) {
2024 if(packmsg_is_array(buf)) {
2025 uint32_t count = packmsg_get_array(buf);
2027 while(count-- && buf->len >= 0) {
2028 packmsg_skip_object(buf);
2030 } else if(packmsg_is_map(buf)) {
2031 uint32_t count = packmsg_get_map(buf);
2033 while(count-- && buf->len >= 0) {
2034 packmsg_skip_object(buf);
2035 packmsg_skip_object(buf);
2038 packmsg_skip_element(buf);