LCOV - code coverage report
Current view: top level - external/msgpuck - msgpuck.h (source / functions) Hit Total Coverage
Test: rapport Lines: 42 607 6.9 %
Date: 2021-12-10 16:22:55 Functions: 10 69 14.5 %
Branches: 13 334 3.9 %

           Branch data     Line data    Source code
       1                 :            : #ifndef MSGPUCK_H_INCLUDED
       2                 :            : #define MSGPUCK_H_INCLUDED
       3                 :            : /*
       4                 :            :  * Copyright (c) 2013-2017 MsgPuck Authors
       5                 :            :  * All rights reserved.
       6                 :            :  *
       7                 :            :  * Redistribution and use in source and binary forms, with or
       8                 :            :  * without modification, are permitted provided that the following
       9                 :            :  * conditions are met:
      10                 :            :  *
      11                 :            :  * 1. Redistributions of source code must retain the above
      12                 :            :  *    copyright notice, this list of conditions and the
      13                 :            :  *    following disclaimer.
      14                 :            :  *
      15                 :            :  * 2. Redistributions in binary form must reproduce the above
      16                 :            :  *    copyright notice, this list of conditions and the following
      17                 :            :  *    disclaimer in the documentation and/or other materials
      18                 :            :  *    provided with the distribution.
      19                 :            :  *
      20                 :            :  * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
      21                 :            :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      22                 :            :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23                 :            :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
      24                 :            :  * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      25                 :            :  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26                 :            :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      27                 :            :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
      28                 :            :  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
      29                 :            :  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      30                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
      31                 :            :  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      32                 :            :  * SUCH DAMAGE.
      33                 :            :  */
      34                 :            : 
      35                 :            : /**
      36                 :            :  * \file msgpuck.h
      37                 :            :  * MsgPuck
      38                 :            :  * \brief MsgPuck is a simple and efficient MsgPack encoder/decoder
      39                 :            :  * library in a single self-contained file.
      40                 :            :  *
      41                 :            :  * Usage example:
      42                 :            :  * \code
      43                 :            :  * // Encode
      44                 :            :  * char buf[1024];
      45                 :            :  * char *w = buf;
      46                 :            :  * w = mp_encode_array(w, 4);
      47                 :            :  * w = mp_encode_uint(w, 10);
      48                 :            :  * w = mp_encode_str(w, "hello world", strlen("hello world"));
      49                 :            :  * w = mp_encode_bool(w, true);
      50                 :            :  * w = mp_encode_double(w, 3.1415);
      51                 :            :  *
      52                 :            :  * // Validate
      53                 :            :  * const char *b = buf;
      54                 :            :  * int r = mp_check(&b, w);
      55                 :            :  * assert(!r);
      56                 :            :  * assert(b == w);
      57                 :            :  *
      58                 :            :  * // Decode
      59                 :            :  * uint32_t size;
      60                 :            :  * uint64_t ival;
      61                 :            :  * const char *sval;
      62                 :            :  * uint32_t sval_len;
      63                 :            :  * bool bval;
      64                 :            :  * double dval;
      65                 :            :  *
      66                 :            :  * const char *r = buf;
      67                 :            :  *
      68                 :            :  * size = mp_decode_array(&r);
      69                 :            :  * // size is 4
      70                 :            :  *
      71                 :            :  * ival = mp_decode_uint(&r);
      72                 :            :  * // ival is 10;
      73                 :            :  *
      74                 :            :  * sval = mp_decode_str(&r, &sval_len);
      75                 :            :  * // sval is "hello world", sval_len is strlen("hello world")
      76                 :            :  *
      77                 :            :  * bval = mp_decode_bool(&r);
      78                 :            :  * // bval is true
      79                 :            :  *
      80                 :            :  * dval = mp_decode_double(&r);
      81                 :            :  * // dval is 3.1415
      82                 :            :  *
      83                 :            :  * assert(r == w);
      84                 :            :  * \endcode
      85                 :            :  *
      86                 :            :  * \note Supported compilers.
      87                 :            :  * The implementation requires a C99+ or C++03+ compatible compiler.
      88                 :            :  *
      89                 :            :  * \note Inline functions.
      90                 :            :  * The implementation is compatible with both C99 and GNU inline functions.
      91                 :            :  * Please link libmsgpuck.a static library for non-inlined versions of
      92                 :            :  * functions and global tables.
      93                 :            :  */
      94                 :            : 
      95                 :            : #if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
      96                 :            : #define __STDC_CONSTANT_MACROS 1 /* make С++ to be happy */
      97                 :            : #endif
      98                 :            : #if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
      99                 :            : #define __STDC_LIMIT_MACROS 1    /* make С++ to be happy */
     100                 :            : #endif
     101                 :            : #include <stdlib.h>
     102                 :            : #include <stdint.h>
     103                 :            : #include <stddef.h>
     104                 :            : #include <stdbool.h>
     105                 :            : #include <string.h>
     106                 :            : #include <assert.h>
     107                 :            : #include <stdarg.h>
     108                 :            : #include <stdio.h>
     109                 :            : 
     110                 :            : #if defined(__cplusplus)
     111                 :            : extern "C" {
     112                 :            : #endif /* defined(__cplusplus) */
     113                 :            : 
     114                 :            : /*
     115                 :            :  * {{{ Platform-specific definitions
     116                 :            :  */
     117                 :            : 
     118                 :            : /** \cond false **/
     119                 :            : 
     120                 :            : #if defined(__CC_ARM)         /* set the alignment to 1 for armcc compiler */
     121                 :            : #define MP_PACKED    __packed
     122                 :            : #else
     123                 :            : #define MP_PACKED  __attribute__((packed))
     124                 :            : #endif
     125                 :            : 
     126                 :            : #if defined(MP_SOURCE)
     127                 :            : #error MP_SOURCE is not supported anymore, please link libmsgpuck.a
     128                 :            : #endif
     129                 :            : 
     130                 :            : #if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__)
     131                 :            : #if !defined(MP_LIBRARY)
     132                 :            : #define MP_PROTO extern inline
     133                 :            : #define MP_IMPL extern inline
     134                 :            : #else /* defined(MP_LIBRARY) */
     135                 :            : #define MP_PROTO
     136                 :            : #define MP_IMPL
     137                 :            : #endif
     138                 :            : #define MP_ALWAYSINLINE
     139                 :            : #else /* C99 inline */
     140                 :            : #if !defined(MP_LIBRARY)
     141                 :            : #define MP_PROTO inline
     142                 :            : #define MP_IMPL inline
     143                 :            : #else /* defined(MP_LIBRARY) */
     144                 :            : #define MP_PROTO extern inline
     145                 :            : #define MP_IMPL inline
     146                 :            : #endif
     147                 :            : #define MP_ALWAYSINLINE __attribute__((always_inline))
     148                 :            : #endif /* GNU inline or C99 inline */
     149                 :            : 
     150                 :            : #if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || \
     151                 :            :         defined __SUNPRO_C || defined __SUNPRO_CC
     152                 :            : #define MP_GCC_VERSION(major, minor) 0
     153                 :            : #else
     154                 :            : #define MP_GCC_VERSION(major, minor) (__GNUC__ > (major) || \
     155                 :            :         (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
     156                 :            : #endif
     157                 :            : 
     158                 :            : #if !defined(__has_builtin)
     159                 :            : #define __has_builtin(x) 0 /* clang */
     160                 :            : #endif
     161                 :            : 
     162                 :            : #if MP_GCC_VERSION(2, 9) || __has_builtin(__builtin_expect)
     163                 :            : #define mp_likely(x) __builtin_expect((x), 1)
     164                 :            : #define mp_unlikely(x) __builtin_expect((x), 0)
     165                 :            : #else
     166                 :            : #define mp_likely(x) (x)
     167                 :            : #define mp_unlikely(x) (x)
     168                 :            : #endif
     169                 :            : 
     170                 :            : #if MP_GCC_VERSION(4, 5) || __has_builtin(__builtin_unreachable)
     171                 :            : #define mp_unreachable() (assert(0), __builtin_unreachable())
     172                 :            : #else
     173                 :            : MP_PROTO void
     174                 :            : mp_unreachable(void) __attribute__((noreturn));
     175                 :            : MP_PROTO void
     176                 :            : mp_unreachable(void) { assert(0); abort(); }
     177                 :            : #define mp_unreachable() (assert(0))
     178                 :            : #endif
     179                 :            : 
     180                 :            : #define mp_identity(x) (x) /* just to simplify mp_load/mp_store macroses */
     181                 :            : 
     182                 :            : #if MP_GCC_VERSION(4, 8) || __has_builtin(__builtin_bswap16)
     183                 :            : #define mp_bswap_u16(x) __builtin_bswap16(x)
     184                 :            : #else /* !MP_GCC_VERSION(4, 8) */
     185                 :            : #define mp_bswap_u16(x) ( \
     186                 :            :         (((x) <<  8) & 0xff00) | \
     187                 :            :         (((x) >>  8) & 0x00ff) )
     188                 :            : #endif
     189                 :            : 
     190                 :            : #if MP_GCC_VERSION(4, 3) || __has_builtin(__builtin_bswap32)
     191                 :            : #define mp_bswap_u32(x) __builtin_bswap32(x)
     192                 :            : #else /* !MP_GCC_VERSION(4, 3) */
     193                 :            : #define mp_bswap_u32(x) ( \
     194                 :            :         (((x) << 24) & UINT32_C(0xff000000)) | \
     195                 :            :         (((x) <<  8) & UINT32_C(0x00ff0000)) | \
     196                 :            :         (((x) >>  8) & UINT32_C(0x0000ff00)) | \
     197                 :            :         (((x) >> 24) & UINT32_C(0x000000ff)) )
     198                 :            : #endif
     199                 :            : 
     200                 :            : #if MP_GCC_VERSION(4, 3) || __has_builtin(__builtin_bswap64)
     201                 :            : #define mp_bswap_u64(x) __builtin_bswap64(x)
     202                 :            : #else /* !MP_GCC_VERSION(4, 3) */
     203                 :            : #define mp_bswap_u64(x) (\
     204                 :            :         (((x) << 56) & UINT64_C(0xff00000000000000)) | \
     205                 :            :         (((x) << 40) & UINT64_C(0x00ff000000000000)) | \
     206                 :            :         (((x) << 24) & UINT64_C(0x0000ff0000000000)) | \
     207                 :            :         (((x) <<  8) & UINT64_C(0x000000ff00000000)) | \
     208                 :            :         (((x) >>  8) & UINT64_C(0x00000000ff000000)) | \
     209                 :            :         (((x) >> 24) & UINT64_C(0x0000000000ff0000)) | \
     210                 :            :         (((x) >> 40) & UINT64_C(0x000000000000ff00)) | \
     211                 :            :         (((x) >> 56) & UINT64_C(0x00000000000000ff)) )
     212                 :            : #endif
     213                 :            : 
     214                 :            : #define MP_LOAD_STORE(name, type, bswap)                                        \
     215                 :            : MP_PROTO type                                                                   \
     216                 :            : mp_load_##name(const char **data);                                              \
     217                 :            : MP_IMPL type                                                                    \
     218                 :            : mp_load_##name(const char **data)                                               \
     219                 :            : {                                                                               \
     220                 :            :         struct MP_PACKED cast { type val; };                                    \
     221                 :            :         type val = bswap(((struct cast *) *data)->val);                              \
     222                 :            :         *data += sizeof(type);                                                  \
     223                 :            :         return val;                                                             \
     224                 :            : }                                                                               \
     225                 :            : MP_PROTO char *                                                                 \
     226                 :            : mp_store_##name(char *data, type val);                                          \
     227                 :            : MP_IMPL char *                                                                  \
     228                 :            : mp_store_##name(char *data, type val)                                           \
     229                 :            : {                                                                               \
     230                 :            :         struct MP_PACKED cast { type val; };                                    \
     231                 :            :         ((struct cast *) (data))->val = bswap(val);                          \
     232                 :            :         return data + sizeof(type);                                             \
     233                 :            : }
     234                 :            : 
     235                 :       6632 : MP_LOAD_STORE(u8, uint8_t, mp_identity);
     236                 :            : 
     237                 :            : #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     238                 :            : 
     239                 :         16 : MP_LOAD_STORE(u16, uint16_t, mp_bswap_u16);
     240                 :          0 : MP_LOAD_STORE(u32, uint32_t, mp_bswap_u32);
     241                 :          0 : MP_LOAD_STORE(u64, uint64_t, mp_bswap_u64);
     242                 :            : 
     243                 :            : #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
     244                 :            : 
     245                 :            : MP_LOAD_STORE(u16, uint16_t, mp_identity);
     246                 :            : MP_LOAD_STORE(u32, uint32_t, mp_identity);
     247                 :            : MP_LOAD_STORE(u64, uint64_t, mp_identity);
     248                 :            : 
     249                 :            : #else
     250                 :            : #error Unsupported __BYTE_ORDER__
     251                 :            : #endif
     252                 :            : 
     253                 :            : #if !defined(__FLOAT_WORD_ORDER__)
     254                 :            : #define __FLOAT_WORD_ORDER__ __BYTE_ORDER__
     255                 :            : #endif /* defined(__FLOAT_WORD_ORDER__) */
     256                 :            : 
     257                 :            : #if __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
     258                 :            : 
     259                 :            : /*
     260                 :            :  * Idiots from msgpack.org byte-swaps even IEEE754 float/double types.
     261                 :            :  * Some platforms (e.g. arm) cause SIGBUS on attempt to store
     262                 :            :  * invalid float in registers, so code like flt = mp_bswap_float(flt)
     263                 :            :  * can't be used here.
     264                 :            :  */
     265                 :            : 
     266                 :            : union MP_PACKED mp_float_cast {
     267                 :            :         uint32_t u32;
     268                 :            :         float f;
     269                 :            : };
     270                 :            : 
     271                 :            : union MP_PACKED mp_double_cast {
     272                 :            :         uint64_t u64;
     273                 :            :         double d;
     274                 :            : };
     275                 :            : 
     276                 :            : MP_PROTO float
     277                 :            : mp_load_float(const char **data);
     278                 :            : MP_PROTO double
     279                 :            : mp_load_double(const char **data);
     280                 :            : MP_PROTO char *
     281                 :            : mp_store_float(char *data, float val);
     282                 :            : MP_PROTO char *
     283                 :            : mp_store_double(char *data, double val);
     284                 :            : 
     285                 :            : MP_IMPL float
     286                 :          0 : mp_load_float(const char **data)
     287                 :            : {
     288                 :          0 :         union mp_float_cast cast = *(union mp_float_cast *) *data;
     289                 :          0 :         *data += sizeof(cast);
     290                 :          0 :         cast.u32 = mp_bswap_u32(cast.u32);
     291                 :          0 :         return cast.f;
     292                 :            : }
     293                 :            : 
     294                 :            : MP_IMPL double
     295                 :          0 : mp_load_double(const char **data)
     296                 :            : {
     297                 :          0 :         union mp_double_cast cast = *(union mp_double_cast *) *data;
     298                 :          0 :         *data += sizeof(cast);
     299                 :          0 :         cast.u64 = mp_bswap_u64(cast.u64);
     300                 :          0 :         return cast.d;
     301                 :            : }
     302                 :            : 
     303                 :            : MP_IMPL char *
     304                 :          0 : mp_store_float(char *data, float val)
     305                 :            : {
     306                 :            :         union mp_float_cast cast;
     307                 :          0 :         cast.f = val;
     308                 :          0 :         cast.u32 = mp_bswap_u32(cast.u32);
     309                 :          0 :         *(union mp_float_cast *) (data) = cast;
     310                 :          0 :         return data + sizeof(cast);
     311                 :            : }
     312                 :            : 
     313                 :            : MP_IMPL char *
     314                 :          0 : mp_store_double(char *data, double val)
     315                 :            : {
     316                 :            :         union mp_double_cast cast;
     317                 :          0 :         cast.d = val;
     318                 :          0 :         cast.u64 = mp_bswap_u64(cast.u64);
     319                 :          0 :         *(union mp_double_cast *) (data) = cast;
     320                 :          0 :         return data + sizeof(cast);
     321                 :            : }
     322                 :            : 
     323                 :            : #elif __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
     324                 :            : 
     325                 :            : MP_LOAD_STORE(float, float, mp_identity);
     326                 :            : MP_LOAD_STORE(double, double, mp_identity);
     327                 :            : 
     328                 :            : #else
     329                 :            : #error Unsupported __FLOAT_WORD_ORDER__
     330                 :            : #endif
     331                 :            : 
     332                 :            : #undef mp_identity
     333                 :            : #undef MP_LOAD_STORE
     334                 :            : 
     335                 :            : /** \endcond */
     336                 :            : 
     337                 :            : /*
     338                 :            :  * }}}
     339                 :            :  */
     340                 :            : 
     341                 :            : /*
     342                 :            :  * {{{ API definition
     343                 :            :  */
     344                 :            : 
     345                 :            : /**
     346                 :            :  * \brief MsgPack data types
     347                 :            :  */
     348                 :            : enum mp_type {
     349                 :            :         MP_NIL = 0,
     350                 :            :         MP_UINT,
     351                 :            :         MP_INT,
     352                 :            :         MP_STR,
     353                 :            :         MP_BIN,
     354                 :            :         MP_ARRAY,
     355                 :            :         MP_MAP,
     356                 :            :         MP_BOOL,
     357                 :            :         MP_FLOAT,
     358                 :            :         MP_DOUBLE,
     359                 :            :         MP_EXT
     360                 :            : };
     361                 :            : 
     362                 :            : /**
     363                 :            :  * \brief Determine MsgPack type by a first byte \a c of encoded data.
     364                 :            :  *
     365                 :            :  * Example usage:
     366                 :            :  * \code
     367                 :            :  * assert(MP_ARRAY == mp_typeof(0x90));
     368                 :            :  * \endcode
     369                 :            :  *
     370                 :            :  * \param c - a first byte of encoded data
     371                 :            :  * \return MsgPack type
     372                 :            :  */
     373                 :            : MP_PROTO __attribute__((pure)) enum mp_type
     374                 :            : mp_typeof(const char c);
     375                 :            : 
     376                 :            : /**
     377                 :            :  * \brief Calculate exact buffer size needed to store an array header of
     378                 :            :  * \a size elements. Maximum return value is 5. For performance reasons you
     379                 :            :  * can preallocate buffer for maximum size without calling the function.
     380                 :            :  * \param size - a number of elements
     381                 :            :  * \return buffer size in bytes (max is 5)
     382                 :            :  */
     383                 :            : MP_PROTO __attribute__((const)) uint32_t
     384                 :            : mp_sizeof_array(uint32_t size);
     385                 :            : 
     386                 :            : /**
     387                 :            :  * \brief Encode an array header of \a size elements.
     388                 :            :  *
     389                 :            :  * All array members must be encoded after the header.
     390                 :            :  *
     391                 :            :  * Example usage:
     392                 :            :  * \code
     393                 :            :  * // Encode
     394                 :            :  * char buf[1024];
     395                 :            :  * char *w = buf;
     396                 :            :  * w = mp_encode_array(w, 2);
     397                 :            :  * w = mp_encode_uint(w, 10);
     398                 :            :  * w = mp_encode_uint(w, 15);
     399                 :            :  *
     400                 :            :  * // Decode
     401                 :            :  * const char *r = buf;
     402                 :            :  * uint32_t size = mp_decode_array(&r);
     403                 :            :  * for (uint32_t i = 0; i < size; i++) {
     404                 :            :  *     uint64_t val = mp_decode_uint(&r);
     405                 :            :  * }
     406                 :            :  * assert (r == w);
     407                 :            :  * \endcode
     408                 :            :  * It is your responsibility to ensure that \a data has enough space.
     409                 :            :  * \param data - a buffer
     410                 :            :  * \param size - a number of elements
     411                 :            :  * \return \a data + \link mp_sizeof_array() mp_sizeof_array(size) \endlink
     412                 :            :  * \sa mp_sizeof_array
     413                 :            :  */
     414                 :            : MP_PROTO char *
     415                 :            : mp_encode_array(char *data, uint32_t size);
     416                 :            : 
     417                 :            : /**
     418                 :            :  * \brief Check that \a cur buffer has enough bytes to decode an array header
     419                 :            :  * \param cur buffer
     420                 :            :  * \param end end of the buffer
     421                 :            :  * \retval 0 - buffer has enough bytes
     422                 :            :  * \retval > 0 - the number of remaining bytes to read
     423                 :            :  * \pre cur < end
     424                 :            :  * \pre mp_typeof(*cur) == MP_ARRAY
     425                 :            :  */
     426                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     427                 :            : mp_check_array(const char *cur, const char *end);
     428                 :            : 
     429                 :            : /**
     430                 :            :  * \brief Decode an array header from MsgPack \a data.
     431                 :            :  *
     432                 :            :  * All array members must be decoded after the header.
     433                 :            :  * \param data - the pointer to a buffer
     434                 :            :  * \return the number of elements in an array
     435                 :            :  * \post *data = *data + mp_sizeof_array(retval)
     436                 :            :  * \sa \link mp_encode_array() An usage example \endlink
     437                 :            :  */
     438                 :            : MP_PROTO uint32_t
     439                 :            : mp_decode_array(const char **data);
     440                 :            : 
     441                 :            : /**
     442                 :            :  * \brief Calculate exact buffer size needed to store a map header of
     443                 :            :  * \a size elements. Maximum return value is 5. For performance reasons you
     444                 :            :  * can preallocate buffer for maximum size without calling the function.
     445                 :            :  * \param size - a number of elements
     446                 :            :  * \return buffer size in bytes (max is 5)
     447                 :            :  */
     448                 :            : MP_PROTO __attribute__((const)) uint32_t
     449                 :            : mp_sizeof_map(uint32_t size);
     450                 :            : 
     451                 :            : /**
     452                 :            :  * \brief Encode a map header of \a size elements.
     453                 :            :  *
     454                 :            :  * All map key-value pairs must be encoded after the header.
     455                 :            :  *
     456                 :            :  * Example usage:
     457                 :            :  * \code
     458                 :            :  * char buf[1024];
     459                 :            :  *
     460                 :            :  * // Encode
     461                 :            :  * char *w = buf;
     462                 :            :  * w = mp_encode_map(b, 2);
     463                 :            :  * w = mp_encode_str(b, "key1", 4);
     464                 :            :  * w = mp_encode_str(b, "value1", 6);
     465                 :            :  * w = mp_encode_str(b, "key2", 4);
     466                 :            :  * w = mp_encode_str(b, "value2", 6);
     467                 :            :  *
     468                 :            :  * // Decode
     469                 :            :  * const char *r = buf;
     470                 :            :  * uint32_t size = mp_decode_map(&r);
     471                 :            :  * for (uint32_t i = 0; i < size; i++) {
     472                 :            :  *      // Use switch(mp_typeof(**r)) to support more types
     473                 :            :  *     uint32_t key_len, val_len;
     474                 :            :  *     const char *key = mp_decode_str(&r, key_len);
     475                 :            :  *     const char *val = mp_decode_str(&r, val_len);
     476                 :            :  * }
     477                 :            :  * assert (r == w);
     478                 :            :  * \endcode
     479                 :            :  * It is your responsibility to ensure that \a data has enough space.
     480                 :            :  * \param data - a buffer
     481                 :            :  * \param size - a number of key/value pairs
     482                 :            :  * \return \a data + \link mp_sizeof_map() mp_sizeof_map(size)\endlink
     483                 :            :  * \sa mp_sizeof_map
     484                 :            :  */
     485                 :            : MP_PROTO char *
     486                 :            : mp_encode_map(char *data, uint32_t size);
     487                 :            : 
     488                 :            : /**
     489                 :            :  * \brief Check that \a cur buffer has enough bytes to decode a map header
     490                 :            :  * \param cur buffer
     491                 :            :  * \param end end of the buffer
     492                 :            :  * \retval 0 - buffer has enough bytes
     493                 :            :  * \retval > 0 - the number of remaining bytes to read
     494                 :            :  * \pre cur < end
     495                 :            :  * \pre mp_typeof(*cur) == MP_MAP
     496                 :            :  */
     497                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     498                 :            : mp_check_map(const char *cur, const char *end);
     499                 :            : 
     500                 :            : /**
     501                 :            :  * \brief Decode a map header from MsgPack \a data.
     502                 :            :  *
     503                 :            :  * All map key-value pairs must be decoded after the header.
     504                 :            :  * \param data - the pointer to a buffer
     505                 :            :  * \return the number of key/value pairs in a map
     506                 :            :  * \post *data = *data + mp_sizeof_array(retval)
     507                 :            :  * \sa \link mp_encode_map() An usage example \endlink
     508                 :            :  */
     509                 :            : MP_PROTO uint32_t
     510                 :            : mp_decode_map(const char **data);
     511                 :            : 
     512                 :            : /**
     513                 :            :  * \brief Calculate exact buffer size needed to store an integer \a num.
     514                 :            :  * Maximum return value is 9. For performance reasons you can preallocate
     515                 :            :  * buffer for maximum size without calling the function.
     516                 :            :  * Example usage:
     517                 :            :  * \code
     518                 :            :  * char **data = ...;
     519                 :            :  * char *end = *data;
     520                 :            :  * my_buffer_ensure(mp_sizeof_uint(x), &end);
     521                 :            :  * // my_buffer_ensure(9, &end);
     522                 :            :  * mp_encode_uint(buffer, x);
     523                 :            :  * \endcode
     524                 :            :  * \param num - a number
     525                 :            :  * \return buffer size in bytes (max is 9)
     526                 :            :  */
     527                 :            : MP_PROTO __attribute__((const)) uint32_t
     528                 :            : mp_sizeof_uint(uint64_t num);
     529                 :            : 
     530                 :            : /**
     531                 :            :  * \brief Calculate exact buffer size needed to store an integer \a num.
     532                 :            :  * Maximum return value is 9. For performance reasons you can preallocate
     533                 :            :  * buffer for maximum size without calling the function.
     534                 :            :  * \param num - a number
     535                 :            :  * \return buffer size in bytes (max is 9)
     536                 :            :  * \pre \a num < 0
     537                 :            :  */
     538                 :            : MP_PROTO __attribute__((const)) uint32_t
     539                 :            : mp_sizeof_int(int64_t num);
     540                 :            : 
     541                 :            : /**
     542                 :            :  * \brief Encode an unsigned integer \a num.
     543                 :            :  * It is your responsibility to ensure that \a data has enough space.
     544                 :            :  * \param data - a buffer
     545                 :            :  * \param num - a number
     546                 :            :  * \return \a data + mp_sizeof_uint(\a num)
     547                 :            :  * \sa \link mp_encode_array() An usage example \endlink
     548                 :            :  * \sa mp_sizeof_uint()
     549                 :            :  */
     550                 :            : MP_PROTO char *
     551                 :            : mp_encode_uint(char *data, uint64_t num);
     552                 :            : 
     553                 :            : /**
     554                 :            :  * \brief Encode a signed integer \a num.
     555                 :            :  * It is your responsibility to ensure that \a data has enough space.
     556                 :            :  * \param data - a buffer
     557                 :            :  * \param num - a number
     558                 :            :  * \return \a data + mp_sizeof_int(\a num)
     559                 :            :  * \sa \link mp_encode_array() An usage example \endlink
     560                 :            :  * \sa mp_sizeof_int()
     561                 :            :  * \pre \a num < 0
     562                 :            :  */
     563                 :            : MP_PROTO char *
     564                 :            : mp_encode_int(char *data, int64_t num);
     565                 :            : 
     566                 :            : /**
     567                 :            :  * \brief Check that \a cur buffer has enough bytes to decode an uint
     568                 :            :  * \param cur buffer
     569                 :            :  * \param end end of the buffer
     570                 :            :  * \retval 0 - buffer has enough bytes
     571                 :            :  * \retval > 0 - the number of remaining bytes to read
     572                 :            :  * \pre cur < end
     573                 :            :  * \pre mp_typeof(*cur) == MP_UINT
     574                 :            :  */
     575                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     576                 :            : mp_check_uint(const char *cur, const char *end);
     577                 :            : 
     578                 :            : /**
     579                 :            :  * \brief Check that \a cur buffer has enough bytes to decode an int
     580                 :            :  * \param cur buffer
     581                 :            :  * \param end end of the buffer
     582                 :            :  * \retval 0 - buffer has enough bytes
     583                 :            :  * \retval > 0 - the number of remaining bytes to read
     584                 :            :  * \pre cur < end
     585                 :            :  * \pre mp_typeof(*cur) == MP_INT
     586                 :            :  */
     587                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     588                 :            : mp_check_int(const char *cur, const char *end);
     589                 :            : 
     590                 :            : /**
     591                 :            :  * \brief Decode an unsigned integer from MsgPack \a data
     592                 :            :  * \param data - the pointer to a buffer
     593                 :            :  * \return an unsigned number
     594                 :            :  * \post *data = *data + mp_sizeof_uint(retval)
     595                 :            :  */
     596                 :            : MP_PROTO uint64_t
     597                 :            : mp_decode_uint(const char **data);
     598                 :            : 
     599                 :            : /**
     600                 :            :  * \brief Decode a signed integer from MsgPack \a data
     601                 :            :  * \param data - the pointer to a buffer
     602                 :            :  * \return an unsigned number
     603                 :            :  * \post *data = *data + mp_sizeof_int(retval)
     604                 :            :  */
     605                 :            : MP_PROTO int64_t
     606                 :            : mp_decode_int(const char **data);
     607                 :            : 
     608                 :            : /**
     609                 :            :  * \brief Compare two packed unsigned integers.
     610                 :            :  *
     611                 :            :  * The function is faster than two mp_decode_uint() calls.
     612                 :            :  * \param data_a unsigned int a
     613                 :            :  * \param data_b unsigned int b
     614                 :            :  * \retval < 0 when \a a < \a b
     615                 :            :  * \retval   0 when \a a == \a b
     616                 :            :  * \retval > 0 when \a a > \a b
     617                 :            :  */
     618                 :            : MP_PROTO __attribute__((pure)) int
     619                 :            : mp_compare_uint(const char *data_a, const char *data_b);
     620                 :            : 
     621                 :            : /**
     622                 :            :  * \brief Calculate exact buffer size needed to store a float \a num.
     623                 :            :  * The return value is always 5. The function was added to provide integrity of
     624                 :            :  * the library.
     625                 :            :  * \param num - a float
     626                 :            :  * \return buffer size in bytes (always 5)
     627                 :            :  */
     628                 :            : MP_PROTO __attribute__((const)) uint32_t
     629                 :            : mp_sizeof_float(float num);
     630                 :            : 
     631                 :            : /**
     632                 :            :  * \brief Calculate exact buffer size needed to store a double \a num.
     633                 :            :  * The return value is either 5 or 9. The function was added to provide
     634                 :            :  * integrity of the library. For performance reasons you can preallocate buffer
     635                 :            :  * for maximum size without calling the function.
     636                 :            :  * \param num - a double
     637                 :            :  * \return buffer size in bytes (5 or 9)
     638                 :            :  */
     639                 :            : MP_PROTO __attribute__((const)) uint32_t
     640                 :            : mp_sizeof_double(double num);
     641                 :            : 
     642                 :            : /**
     643                 :            :  * \brief Encode a float \a num.
     644                 :            :  * It is your responsibility to ensure that \a data has enough space.
     645                 :            :  * \param data - a buffer
     646                 :            :  * \param num - a float
     647                 :            :  * \return \a data + mp_sizeof_float(\a num)
     648                 :            :  * \sa mp_sizeof_float()
     649                 :            :  * \sa \link mp_encode_array() An usage example \endlink
     650                 :            :  */
     651                 :            : MP_PROTO char *
     652                 :            : mp_encode_float(char *data, float num);
     653                 :            : 
     654                 :            : /**
     655                 :            :  * \brief Encode a double \a num.
     656                 :            :  * It is your responsibility to ensure that \a data has enough space.
     657                 :            :  * \param data - a buffer
     658                 :            :  * \param num - a float
     659                 :            :  * \return \a data + mp_sizeof_double(\a num)
     660                 :            :  * \sa \link mp_encode_array() An usage example \endlink
     661                 :            :  * \sa mp_sizeof_double()
     662                 :            :  */
     663                 :            : MP_PROTO char *
     664                 :            : mp_encode_double(char *data, double num);
     665                 :            : 
     666                 :            : /**
     667                 :            :  * \brief Check that \a cur buffer has enough bytes to decode a float
     668                 :            :  * \param cur buffer
     669                 :            :  * \param end end of the buffer
     670                 :            :  * \retval 0 - buffer has enough bytes
     671                 :            :  * \retval > 0 - the number of remaining bytes to read
     672                 :            :  * \pre cur < end
     673                 :            :  * \pre mp_typeof(*cur) == MP_FLOAT
     674                 :            :  */
     675                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     676                 :            : mp_check_float(const char *cur, const char *end);
     677                 :            : 
     678                 :            : /**
     679                 :            :  * \brief Check that \a cur buffer has enough bytes to decode a double
     680                 :            :  * \param cur buffer
     681                 :            :  * \param end end of the buffer
     682                 :            :  * \retval 0 - buffer has enough bytes
     683                 :            :  * \retval > 0 - the number of remaining bytes to read
     684                 :            :  * \pre cur < end
     685                 :            :  * \pre mp_typeof(*cur) == MP_DOUBLE
     686                 :            :  */
     687                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     688                 :            : mp_check_double(const char *cur, const char *end);
     689                 :            : 
     690                 :            : /**
     691                 :            :  * \brief Decode a float from MsgPack \a data
     692                 :            :  * \param data - the pointer to a buffer
     693                 :            :  * \return a float
     694                 :            :  * \post *data = *data + mp_sizeof_float(retval)
     695                 :            :  */
     696                 :            : MP_PROTO float
     697                 :            : mp_decode_float(const char **data);
     698                 :            : 
     699                 :            : /**
     700                 :            :  * \brief Decode a double from MsgPack \a data
     701                 :            :  * \param data - the pointer to a buffer
     702                 :            :  * \return a double
     703                 :            :  * \post *data = *data + mp_sizeof_double(retval)
     704                 :            :  */
     705                 :            : MP_PROTO double
     706                 :            : mp_decode_double(const char **data);
     707                 :            : 
     708                 :            : /**
     709                 :            :  * \brief Calculate exact buffer size needed to store a string header of
     710                 :            :  * length \a num. Maximum return value is 5. For performance reasons you can
     711                 :            :  * preallocate buffer for maximum size without calling the function.
     712                 :            :  * \param len - a string length
     713                 :            :  * \return size in chars (max is 5)
     714                 :            :  */
     715                 :            : MP_PROTO __attribute__((const)) uint32_t
     716                 :            : mp_sizeof_strl(uint32_t len);
     717                 :            : 
     718                 :            : /**
     719                 :            :  * \brief Equivalent to mp_sizeof_strl(\a len) + \a len.
     720                 :            :  * \param len - a string length
     721                 :            :  * \return size in chars (max is 5 + \a len)
     722                 :            :  */
     723                 :            : MP_PROTO __attribute__((const)) uint32_t
     724                 :            : mp_sizeof_str(uint32_t len);
     725                 :            : 
     726                 :            : /**
     727                 :            :  * \brief Calculate exact buffer size needed to store a binstring header of
     728                 :            :  * length \a num. Maximum return value is 5. For performance reasons you can
     729                 :            :  * preallocate buffer for maximum size without calling the function.
     730                 :            :  * \param len - a string length
     731                 :            :  * \return size in chars (max is 5)
     732                 :            :  */
     733                 :            : MP_PROTO __attribute__((const)) uint32_t
     734                 :            : mp_sizeof_binl(uint32_t len);
     735                 :            : 
     736                 :            : /**
     737                 :            :  * \brief Equivalent to mp_sizeof_binl(\a len) + \a len.
     738                 :            :  * \param len - a string length
     739                 :            :  * \return size in chars (max is 5 + \a len)
     740                 :            :  */
     741                 :            : MP_PROTO __attribute__((const)) uint32_t
     742                 :            : mp_sizeof_bin(uint32_t len);
     743                 :            : 
     744                 :            : /**
     745                 :            :  * \brief Encode a string header of length \a len.
     746                 :            :  *
     747                 :            :  * The function encodes MsgPack header (\em only header) for a string of
     748                 :            :  * length \a len. You should append actual string data to the buffer manually
     749                 :            :  * after encoding the header (exactly \a len bytes without trailing '\0').
     750                 :            :  *
     751                 :            :  * This approach is very useful for cases when the total length of the string
     752                 :            :  * is known in advance, but the string data is not stored in a single
     753                 :            :  * continuous buffer (e.g. network packets).
     754                 :            :  *
     755                 :            :  * It is your responsibility to ensure that \a data has enough space.
     756                 :            :  * Usage example:
     757                 :            :  * \code
     758                 :            :  * char buffer[1024];
     759                 :            :  * char *b = buffer;
     760                 :            :  * b = mp_encode_strl(b, hdr.total_len);
     761                 :            :  * char *s = b;
     762                 :            :  * memcpy(b, pkt1.data, pkt1.len);
     763                 :            :  * b += pkt1.len;
     764                 :            :  * // get next packet
     765                 :            :  * memcpy(b, pkt2.data, pkt2.len);
     766                 :            :  * b += pkt2.len;
     767                 :            :  * // get next packet
     768                 :            :  * memcpy(b, pkt1.data, pkt3.len);
     769                 :            :  * b += pkt3.len;
     770                 :            :  *
     771                 :            :  * // Check that all data was received
     772                 :            :  * assert(hdr.total_len == (uint32_t) (b - s))
     773                 :            :  * \endcode
     774                 :            :  * Hint: you can dynamically reallocate the buffer during the process.
     775                 :            :  * \param data - a buffer
     776                 :            :  * \param len - a string length
     777                 :            :  * \return \a data + mp_sizeof_strl(len)
     778                 :            :  * \sa mp_sizeof_strl()
     779                 :            :  */
     780                 :            : MP_PROTO char *
     781                 :            : mp_encode_strl(char *data, uint32_t len);
     782                 :            : 
     783                 :            : /**
     784                 :            :  * \brief Encode a string of length \a len.
     785                 :            :  * The function is equivalent to mp_encode_strl() + memcpy.
     786                 :            :  * \param data - a buffer
     787                 :            :  * \param str - a pointer to string data
     788                 :            :  * \param len - a string length
     789                 :            :  * \return \a data + mp_sizeof_str(len) ==
     790                 :            :  * data + mp_sizeof_strl(len) + len
     791                 :            :  * \sa mp_encode_strl
     792                 :            :  */
     793                 :            : MP_PROTO char *
     794                 :            : mp_encode_str(char *data, const char *str, uint32_t len);
     795                 :            : 
     796                 :            : /**
     797                 :            :  * \brief Encode a binstring header of length \a len.
     798                 :            :  * See mp_encode_strl() for more details.
     799                 :            :  * \param data - a bufer
     800                 :            :  * \param len - a string length
     801                 :            :  * \return data + mp_sizeof_binl(\a len)
     802                 :            :  * \sa mp_encode_strl
     803                 :            :  */
     804                 :            : MP_PROTO char *
     805                 :            : mp_encode_binl(char *data, uint32_t len);
     806                 :            : 
     807                 :            : /**
     808                 :            :  * \brief Encode a binstring of length \a len.
     809                 :            :  * The function is equivalent to mp_encode_binl() + memcpy.
     810                 :            :  * \param data - a buffer
     811                 :            :  * \param str - a pointer to binstring data
     812                 :            :  * \param len - a binstring length
     813                 :            :  * \return \a data + mp_sizeof_bin(\a len) ==
     814                 :            :  * data + mp_sizeof_binl(\a len) + \a len
     815                 :            :  * \sa mp_encode_strl
     816                 :            :  */
     817                 :            : MP_PROTO char *
     818                 :            : mp_encode_bin(char *data, const char *str, uint32_t len);
     819                 :            : 
     820                 :            : /**
     821                 :            :  * \brief Encode a sequence of values according to format string.
     822                 :            :  * Example: mp_format(buf, sz, "[%d {%d%s%d%s}]", 42, 0, "false", 1, "true");
     823                 :            :  * to get a msgpack array of two items: number 42 and map (0->"false, 2->"true")
     824                 :            :  * Does not write items that don't fit to data_size argument.
     825                 :            :  *
     826                 :            :  * \param data - a buffer
     827                 :            :  * \param data_size - a buffer size
     828                 :            :  * \param format - zero-end string, containing structure of resulting
     829                 :            :  * msgpack and types of next arguments.
     830                 :            :  * Format can contain '[' and ']' pairs, defining arrays,
     831                 :            :  * '{' and '}' pairs, defining maps, and format specifiers, described below:
     832                 :            :  * %d, %i - int
     833                 :            :  * %u - unsigned int
     834                 :            :  * %ld, %li - long
     835                 :            :  * %lu - unsigned long
     836                 :            :  * %lld, %lli - long long
     837                 :            :  * %llu - unsigned long long
     838                 :            :  * %hd, %hi - short
     839                 :            :  * %hu - unsigned short
     840                 :            :  * %hhd, %hhi - char (as number)
     841                 :            :  * %hhu - unsigned char (as number)
     842                 :            :  * %f - float
     843                 :            :  * %lf - double
     844                 :            :  * %b - bool
     845                 :            :  * %s - zero-end string
     846                 :            :  * %.*s - string with specified length
     847                 :            :  * %p - MsgPack data
     848                 :            :  * %.*p - MsgPack data with specified length
     849                 :            :  * %% is ignored
     850                 :            :  * %smthelse assert and undefined behaviour
     851                 :            :  * NIL - a nil value
     852                 :            :  * all other symbols are ignored.
     853                 :            :  *
     854                 :            :  * \return the number of requred bytes.
     855                 :            :  * \retval > data_size means that is not enough space
     856                 :            :  * and whole msgpack was not encoded.
     857                 :            :  */
     858                 :            : size_t
     859                 :            : mp_format(char *data, size_t data_size, const char *format, ...);
     860                 :            : 
     861                 :            : /**
     862                 :            :  * \brief mp_format variation, taking variable argument list
     863                 :            :  * Example:
     864                 :            :  *  va_list args;
     865                 :            :  *  va_start(args, fmt);
     866                 :            :  *  mp_vformat(data, data_size, fmt, args);
     867                 :            :  *  va_end(args);
     868                 :            :  * \sa \link mp_format() mp_format() \endlink
     869                 :            :  */
     870                 :            : size_t
     871                 :            : mp_vformat(char *data, size_t data_size, const char *format, va_list args);
     872                 :            : 
     873                 :            : /**
     874                 :            :  * \brief print MsgPack data \a file using JSON-like format.
     875                 :            :  * MP_EXT is printed as "undefined"
     876                 :            :  * \param file - pointer to file (or NULL for stdout)
     877                 :            :  * \param data - pointer to buffer containing msgpack object
     878                 :            :  * \retval >=0 - the number of bytes printed
     879                 :            :  * \retval -1 - error
     880                 :            :  * \sa fprintf()
     881                 :            :  */
     882                 :            : int
     883                 :            : mp_fprint(FILE *file, const char *data);
     884                 :            : 
     885                 :            : /**
     886                 :            :  * \brief format MsgPack data to \a buf using JSON-like format.
     887                 :            :  * \sa mp_fprint()
     888                 :            :  * \param buf - buffer to use
     889                 :            :  * \param size - buffer size. This function write at most size bytes
     890                 :            :  * (including the terminating null byte ('\0').
     891                 :            :  * \param data - pointer to buffer containing msgpack object
     892                 :            :  * \retval <size - the number of characters printed (excluding the null byte)
     893                 :            :  * \retval >=size - the number of characters (excluding the null byte),
     894                 :            :  *                  which would have been written to the final string if
     895                 :            :  *                  enough space had been available.
     896                 :            :  * \retval -1 - error
     897                 :            :  * \sa snprintf()
     898                 :            :  */
     899                 :            : int
     900                 :            : mp_snprint(char *buf, int size, const char *data);
     901                 :            : 
     902                 :            : /**
     903                 :            :  * \brief Check that \a cur buffer has enough bytes to decode a string header
     904                 :            :  * \param cur buffer
     905                 :            :  * \param end end of the buffer
     906                 :            :  * \retval 0 - buffer has enough bytes
     907                 :            :  * \retval > 0 - the number of remaining bytes to read
     908                 :            :  * \pre cur < end
     909                 :            :  * \pre mp_typeof(*cur) == MP_STR
     910                 :            :  */
     911                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     912                 :            : mp_check_strl(const char *cur, const char *end);
     913                 :            : 
     914                 :            : /**
     915                 :            :  * \brief Check that \a cur buffer has enough bytes to decode a binstring header
     916                 :            :  * \param cur buffer
     917                 :            :  * \param end end of the buffer
     918                 :            :  * \retval 0 - buffer has enough bytes
     919                 :            :  * \retval > 0 - the number of remaining bytes to read
     920                 :            :  * \pre cur < end
     921                 :            :  * \pre mp_typeof(*cur) == MP_BIN
     922                 :            :  */
     923                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
     924                 :            : mp_check_binl(const char *cur, const char *end);
     925                 :            : 
     926                 :            : /**
     927                 :            :  * \brief Decode a length of a string from MsgPack \a data
     928                 :            :  * \param data - the pointer to a buffer
     929                 :            :  * \return a length of astring
     930                 :            :  * \post *data = *data + mp_sizeof_strl(retval)
     931                 :            :  * \sa mp_encode_strl
     932                 :            :  */
     933                 :            : MP_PROTO uint32_t
     934                 :            : mp_decode_strl(const char **data);
     935                 :            : 
     936                 :            : /**
     937                 :            :  * \brief Decode a string from MsgPack \a data
     938                 :            :  * \param data - the pointer to a buffer
     939                 :            :  * \param len - the pointer to save a string length
     940                 :            :  * \return a pointer to a decoded string
     941                 :            :  * \post *data = *data + mp_sizeof_str(*len)
     942                 :            :  * \sa mp_encode_binl
     943                 :            :  */
     944                 :            : MP_PROTO const char *
     945                 :            : mp_decode_str(const char **data, uint32_t *len);
     946                 :            : 
     947                 :            : /**
     948                 :            :  * \brief Decode a length of a binstring from MsgPack \a data
     949                 :            :  * \param data - the pointer to a buffer
     950                 :            :  * \return a length of a binstring
     951                 :            :  * \post *data = *data + mp_sizeof_binl(retval)
     952                 :            :  * \sa mp_encode_binl
     953                 :            :  */
     954                 :            : MP_PROTO uint32_t
     955                 :            : mp_decode_binl(const char **data);
     956                 :            : 
     957                 :            : /**
     958                 :            :  * \brief Decode a binstring from MsgPack \a data
     959                 :            :  * \param data - the pointer to a buffer
     960                 :            :  * \param len - the pointer to save a binstring length
     961                 :            :  * \return a pointer to a decoded binstring
     962                 :            :  * \post *data = *data + mp_sizeof_str(*len)
     963                 :            :  * \sa mp_encode_binl
     964                 :            :  */
     965                 :            : MP_PROTO const char *
     966                 :            : mp_decode_bin(const char **data, uint32_t *len);
     967                 :            : 
     968                 :            : /**
     969                 :            :  * \brief Decode a length of a string or binstring from MsgPack \a data
     970                 :            :  * \param data - the pointer to a buffer
     971                 :            :  * \return a length of a string
     972                 :            :  * \post *data = *data + mp_sizeof_strbinl(retval)
     973                 :            :  * \sa mp_encode_binl
     974                 :            :  */
     975                 :            : MP_PROTO uint32_t
     976                 :            : mp_decode_strbinl(const char **data);
     977                 :            : 
     978                 :            : /**
     979                 :            :  * \brief Decode a string or binstring from MsgPack \a data
     980                 :            :  * \param data - the pointer to a buffer
     981                 :            :  * \param len - the pointer to save a binstring length
     982                 :            :  * \return a pointer to a decoded binstring
     983                 :            :  * \post *data = *data + mp_sizeof_strbinl(*len)
     984                 :            :  * \sa mp_encode_binl
     985                 :            :  */
     986                 :            : MP_PROTO const char *
     987                 :            : mp_decode_strbin(const char **data, uint32_t *len);
     988                 :            : 
     989                 :            : /**
     990                 :            :  * \brief Calculate exact buffer size needed to store the nil value.
     991                 :            :  * The return value is always 1. The function was added to provide integrity of
     992                 :            :  * the library.
     993                 :            :  * \return buffer size in bytes (always 1)
     994                 :            :  */
     995                 :            : MP_PROTO __attribute__((const)) uint32_t
     996                 :            : mp_sizeof_nil(void);
     997                 :            : 
     998                 :            : /**
     999                 :            :  * \brief Encode the nil value.
    1000                 :            :  * It is your responsibility to ensure that \a data has enough space.
    1001                 :            :  * \param data - a buffer
    1002                 :            :  * \return \a data + mp_sizeof_nil()
    1003                 :            :  * \sa \link mp_encode_array() An usage example \endlink
    1004                 :            :  * \sa mp_sizeof_nil()
    1005                 :            :  */
    1006                 :            : MP_PROTO char *
    1007                 :            : mp_encode_nil(char *data);
    1008                 :            : 
    1009                 :            : /**
    1010                 :            :  * \brief Check that \a cur buffer has enough bytes to decode nil
    1011                 :            :  * \param cur buffer
    1012                 :            :  * \param end end of the buffer
    1013                 :            :  * \retval 0 - buffer has enough bytes
    1014                 :            :  * \retval > 0 - the number of remaining bytes to read
    1015                 :            :  * \pre cur < end
    1016                 :            :  * \pre mp_typeof(*cur) == MP_NIL
    1017                 :            :  */
    1018                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
    1019                 :            : mp_check_nil(const char *cur, const char *end);
    1020                 :            : 
    1021                 :            : /**
    1022                 :            :  * \brief Decode the nil value from MsgPack \a data
    1023                 :            :  * \param data - the pointer to a buffer
    1024                 :            :  * \post *data = *data + mp_sizeof_nil()
    1025                 :            :  */
    1026                 :            : MP_PROTO void
    1027                 :            : mp_decode_nil(const char **data);
    1028                 :            : 
    1029                 :            : /**
    1030                 :            :  * \brief Calculate exact buffer size needed to store a boolean value.
    1031                 :            :  * The return value is always 1. The function was added to provide integrity of
    1032                 :            :  * the library.
    1033                 :            :  * \return buffer size in bytes (always 1)
    1034                 :            :  */
    1035                 :            : MP_PROTO __attribute__((const)) uint32_t
    1036                 :            : mp_sizeof_bool(bool val);
    1037                 :            : 
    1038                 :            : /**
    1039                 :            :  * \brief Encode a bool value \a val.
    1040                 :            :  * It is your responsibility to ensure that \a data has enough space.
    1041                 :            :  * \param data - a buffer
    1042                 :            :  * \param val - a bool
    1043                 :            :  * \return \a data + mp_sizeof_bool(val)
    1044                 :            :  * \sa \link mp_encode_array() An usage example \endlink
    1045                 :            :  * \sa mp_sizeof_bool()
    1046                 :            :  */
    1047                 :            : MP_PROTO char *
    1048                 :            : mp_encode_bool(char *data, bool val);
    1049                 :            : 
    1050                 :            : /**
    1051                 :            :  * \brief Check that \a cur buffer has enough bytes to decode a bool value
    1052                 :            :  * \param cur buffer
    1053                 :            :  * \param end end of the buffer
    1054                 :            :  * \retval 0 - buffer has enough bytes
    1055                 :            :  * \retval > 0 - the number of remaining bytes to read
    1056                 :            :  * \pre cur < end
    1057                 :            :  * \pre mp_typeof(*cur) == MP_BOOL
    1058                 :            :  */
    1059                 :            : MP_PROTO __attribute__((pure)) ptrdiff_t
    1060                 :            : mp_check_bool(const char *cur, const char *end);
    1061                 :            : 
    1062                 :            : /**
    1063                 :            :  * \brief Decode a bool value from MsgPack \a data
    1064                 :            :  * \param data - the pointer to a buffer
    1065                 :            :  * \return a decoded bool value
    1066                 :            :  * \post *data = *data + mp_sizeof_bool(retval)
    1067                 :            :  */
    1068                 :            : MP_PROTO bool
    1069                 :            : mp_decode_bool(const char **data);
    1070                 :            : 
    1071                 :            : /**
    1072                 :            :  * \brief Decode an integer value as int32_t from MsgPack \a data.
    1073                 :            :  * \param data - the pointer to a buffer
    1074                 :            :  * \param[out] ret - the pointer to save a result
    1075                 :            :  * \retval  0 on success
    1076                 :            :  * \retval -1 if underlying mp type is not MP_INT or MP_UINT
    1077                 :            :  * \retval -1 if the result can't be stored in int32_t
    1078                 :            :  */
    1079                 :            : MP_PROTO int
    1080                 :            : mp_read_int32(const char **data, int32_t *ret);
    1081                 :            : 
    1082                 :            : /**
    1083                 :            :  * \brief Decode an integer value as int64_t from MsgPack \a data.
    1084                 :            :  * \param data - the pointer to a buffer
    1085                 :            :  * \param[out] ret - the pointer to save a result
    1086                 :            :  * \retval  0 on success
    1087                 :            :  * \retval -1 if underlying mp type is not MP_INT or MP_UINT
    1088                 :            :  * \retval -1 if the result can't be stored in int64_t
    1089                 :            :  */
    1090                 :            : MP_PROTO int
    1091                 :            : mp_read_int64(const char **data, int64_t *ret);
    1092                 :            : 
    1093                 :            : /**
    1094                 :            :  * \brief Decode a floating point value as double from MsgPack \a data.
    1095                 :            :  * \param data - the pointer to a buffer
    1096                 :            :  * \param[out] ret - the pointer to save a result
    1097                 :            :  * \retval  0 on success
    1098                 :            :  * \retval -1 if underlying mp type is not MP_INT, MP_UINT,
    1099                 :            :  *            MP_FLOAT, or MP_DOUBLE
    1100                 :            :  * \retval -1 if the result can't be stored in double
    1101                 :            :  */
    1102                 :            : MP_PROTO int
    1103                 :            : mp_read_double(const char **data, double *ret);
    1104                 :            : 
    1105                 :            : /**
    1106                 :            :  * \brief Skip one element in a packed \a data.
    1107                 :            :  *
    1108                 :            :  * The function is faster than mp_typeof + mp_decode_XXX() combination.
    1109                 :            :  * For arrays and maps the function also skips all members.
    1110                 :            :  * For strings and binstrings the function also skips the string data.
    1111                 :            :  *
    1112                 :            :  * Usage example:
    1113                 :            :  * \code
    1114                 :            :  * char buf[1024];
    1115                 :            :  *
    1116                 :            :  * char *w = buf;
    1117                 :            :  * // First MsgPack object
    1118                 :            :  * w = mp_encode_uint(w, 10);
    1119                 :            :  *
    1120                 :            :  * // Second MsgPack object
    1121                 :            :  * w = mp_encode_array(w, 4);
    1122                 :            :  *    w = mp_encode_array(w, 2);
    1123                 :            :  *         // Begin of an inner array
    1124                 :            :  *         w = mp_encode_str(w, "second inner 1", 14);
    1125                 :            :  *         w = mp_encode_str(w, "second inner 2", 14);
    1126                 :            :  *         // End of an inner array
    1127                 :            :  *    w = mp_encode_str(w, "second", 6);
    1128                 :            :  *    w = mp_encode_uint(w, 20);
    1129                 :            :  *    w = mp_encode_bool(w, true);
    1130                 :            :  *
    1131                 :            :  * // Third MsgPack object
    1132                 :            :  * w = mp_encode_str(w, "third", 5);
    1133                 :            :  * // EOF
    1134                 :            :  *
    1135                 :            :  * const char *r = buf;
    1136                 :            :  *
    1137                 :            :  * // First MsgPack object
    1138                 :            :  * assert(mp_typeof(**r) == MP_UINT);
    1139                 :            :  * mp_next(&r); // skip the first object
    1140                 :            :  *
    1141                 :            :  * // Second MsgPack object
    1142                 :            :  * assert(mp_typeof(**r) == MP_ARRAY);
    1143                 :            :  * mp_decode_array(&r);
    1144                 :            :  *     assert(mp_typeof(**r) == MP_ARRAY); // inner array
    1145                 :            :  *     mp_next(&r); // -->> skip the entire inner array (with all members)
    1146                 :            :  *     assert(mp_typeof(**r) == MP_STR); // second
    1147                 :            :  *     mp_next(&r);
    1148                 :            :  *     assert(mp_typeof(**r) == MP_UINT); // 20
    1149                 :            :  *     mp_next(&r);
    1150                 :            :  *     assert(mp_typeof(**r) == MP_BOOL); // true
    1151                 :            :  *     mp_next(&r);
    1152                 :            :  *
    1153                 :            :  * // Third MsgPack object
    1154                 :            :  * assert(mp_typeof(**r) == MP_STR); // third
    1155                 :            :  * mp_next(&r);
    1156                 :            :  *
    1157                 :            :  * assert(r == w); // EOF
    1158                 :            :  *
    1159                 :            :  * \endcode
    1160                 :            :  * \param data - the pointer to a buffer
    1161                 :            :  * \post *data = *data + mp_sizeof_TYPE() where TYPE is mp_typeof(**data)
    1162                 :            :  */
    1163                 :            : MP_PROTO void
    1164                 :            : mp_next(const char **data);
    1165                 :            : 
    1166                 :            : /**
    1167                 :            :  * \brief Equivalent to mp_next() but also validates MsgPack in \a data.
    1168                 :            :  * \param data - the pointer to a buffer
    1169                 :            :  * \param end - the end of a buffer
    1170                 :            :  * \retval 0 when MsgPack in \a data is valid.
    1171                 :            :  * \retval != 0 when MsgPack in \a data is not valid.
    1172                 :            :  * \post *data = *data + mp_sizeof_TYPE() where TYPE is mp_typeof(**data)
    1173                 :            :  * \post *data is not defined if MsgPack is not valid
    1174                 :            :  * \sa mp_next()
    1175                 :            :  */
    1176                 :            : MP_PROTO int
    1177                 :            : mp_check(const char **data, const char *end);
    1178                 :            : 
    1179                 :            : /*
    1180                 :            :  * }}}
    1181                 :            :  */
    1182                 :            : 
    1183                 :            : /*
    1184                 :            :  * {{{ Implementation
    1185                 :            :  */
    1186                 :            : 
    1187                 :            : /** \cond false */
    1188                 :            : extern const enum mp_type mp_type_hint[];
    1189                 :            : extern const int8_t mp_parser_hint[];
    1190                 :            : extern const char *mp_char2escape[];
    1191                 :            : 
    1192                 :            : MP_IMPL MP_ALWAYSINLINE enum mp_type
    1193                 :          0 : mp_typeof(const char c)
    1194                 :            : {
    1195                 :          0 :         return mp_type_hint[(uint8_t) c];
    1196                 :            : }
    1197                 :            : 
    1198                 :            : MP_IMPL uint32_t
    1199                 :          0 : mp_sizeof_array(uint32_t size)
    1200                 :            : {
    1201         [ #  # ]:          0 :         if (size <= 15) {
    1202                 :          0 :                 return 1;
    1203         [ #  # ]:          0 :         } else if (size <= UINT16_MAX) {
    1204                 :          0 :                 return 1 + sizeof(uint16_t);
    1205                 :            :         } else {
    1206                 :          0 :                 return 1 + sizeof(uint32_t);
    1207                 :            :         }
    1208                 :          0 : }
    1209                 :            : 
    1210                 :            : MP_IMPL char *
    1211                 :       1068 : mp_encode_array(char *data, uint32_t size)
    1212                 :            : {
    1213         [ +  - ]:       1068 :         if (size <= 15) {
    1214                 :       1068 :                 return mp_store_u8(data, 0x90 | size);
    1215         [ #  # ]:          0 :         } else if (size <= UINT16_MAX) {
    1216                 :          0 :                 data = mp_store_u8(data, 0xdc);
    1217                 :          0 :                 data = mp_store_u16(data, size);
    1218                 :          0 :                 return data;
    1219                 :            :         } else {
    1220                 :          0 :                 data = mp_store_u8(data, 0xdd);
    1221                 :          0 :                 return mp_store_u32(data, size);
    1222                 :            :         }
    1223                 :       1068 : }
    1224                 :            : 
    1225                 :            : MP_IMPL ptrdiff_t
    1226                 :          0 : mp_check_array(const char *cur, const char *end)
    1227                 :            : {
    1228         [ #  # ]:          0 :         assert(cur < end);
    1229         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_ARRAY);
    1230                 :          0 :         uint8_t c = mp_load_u8(&cur);
    1231         [ #  # ]:          0 :         if (mp_likely(!(c & 0x40)))
    1232                 :          0 :                 return cur - end;
    1233                 :            : 
    1234         [ #  # ]:          0 :         assert(c >= 0xdc && c <= 0xdd); /* must be checked above by mp_typeof */
    1235                 :          0 :         uint32_t hsize = 2U << (c & 0x1); /* 0xdc->2, 0xdd->4 */
    1236                 :          0 :         return hsize - (end - cur);
    1237                 :          0 : }
    1238                 :            : 
    1239                 :            : MP_PROTO uint32_t
    1240                 :            : mp_decode_array_slowpath(uint8_t c, const char **data);
    1241                 :            : 
    1242                 :            : MP_IMPL uint32_t
    1243                 :          0 : mp_decode_array_slowpath(uint8_t c, const char **data)
    1244                 :            : {
    1245                 :            :         uint32_t size;
    1246      [ #  #  # ]:          0 :         switch (c & 0x1) {
    1247                 :            :         case 0xdc & 0x1:
    1248                 :          0 :                 size = mp_load_u16(data);
    1249                 :          0 :                 return size;
    1250                 :            :         case 0xdd & 0x1:
    1251                 :          0 :                 size = mp_load_u32(data);
    1252                 :          0 :                 return size;
    1253                 :            :         default:
    1254                 :          0 :                 mp_unreachable();
    1255                 :            :         }
    1256                 :          0 : }
    1257                 :            : 
    1258                 :            : MP_IMPL MP_ALWAYSINLINE uint32_t
    1259                 :       1614 : mp_decode_array(const char **data)
    1260                 :            : {
    1261                 :       1614 :         uint8_t c = mp_load_u8(data);
    1262                 :            : 
    1263         [ +  - ]:       1614 :         if (mp_likely(!(c & 0x40)))
    1264                 :       1614 :                 return (c & 0xf);
    1265                 :            : 
    1266                 :          0 :         return mp_decode_array_slowpath(c, data);
    1267                 :       1614 : }
    1268                 :            : 
    1269                 :            : MP_IMPL uint32_t
    1270                 :          0 : mp_sizeof_map(uint32_t size)
    1271                 :            : {
    1272         [ #  # ]:          0 :         if (size <= 15) {
    1273                 :          0 :                 return 1;
    1274         [ #  # ]:          0 :         } else if (size <= UINT16_MAX) {
    1275                 :          0 :                 return 1 + sizeof(uint16_t);
    1276                 :            :         } else {
    1277                 :          0 :                 return 1 + sizeof(uint32_t);
    1278                 :            :         }
    1279                 :          0 : }
    1280                 :            : 
    1281                 :            : MP_IMPL char *
    1282                 :          0 : mp_encode_map(char *data, uint32_t size)
    1283                 :            : {
    1284         [ #  # ]:          0 :         if (size <= 15) {
    1285                 :          0 :                 return mp_store_u8(data, 0x80 | size);
    1286         [ #  # ]:          0 :         } else if (size <= UINT16_MAX) {
    1287                 :          0 :                 data = mp_store_u8(data, 0xde);
    1288                 :          0 :                 data = mp_store_u16(data, size);
    1289                 :          0 :                 return data;
    1290                 :            :         } else {
    1291                 :          0 :                 data = mp_store_u8(data, 0xdf);
    1292                 :          0 :                 data = mp_store_u32(data, size);
    1293                 :          0 :                 return data;
    1294                 :            :         }
    1295                 :          0 : }
    1296                 :            : 
    1297                 :            : MP_IMPL ptrdiff_t
    1298                 :          0 : mp_check_map(const char *cur, const char *end)
    1299                 :            : {
    1300         [ #  # ]:          0 :         assert(cur < end);
    1301         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_MAP);
    1302                 :          0 :         uint8_t c = mp_load_u8(&cur);
    1303         [ #  # ]:          0 :         if (mp_likely((c & ~0xfU) == 0x80))
    1304                 :          0 :                 return cur - end;
    1305                 :            : 
    1306         [ #  # ]:          0 :         assert(c >= 0xde && c <= 0xdf); /* must be checked above by mp_typeof */
    1307                 :          0 :         uint32_t hsize = 2U << (c & 0x1); /* 0xde->2, 0xdf->4 */
    1308                 :          0 :         return hsize - (end - cur);
    1309                 :          0 : }
    1310                 :            : 
    1311                 :            : MP_IMPL uint32_t
    1312                 :          0 : mp_decode_map(const char **data)
    1313                 :            : {
    1314                 :          0 :         uint8_t c = mp_load_u8(data);
    1315      [ #  #  # ]:          0 :         switch (c) {
    1316                 :            :         case 0xde:
    1317                 :          0 :                 return mp_load_u16(data);
    1318                 :            :         case 0xdf:
    1319                 :          0 :                 return mp_load_u32(data);
    1320                 :            :         default:
    1321   [ #  #  #  # ]:          0 :                 if (mp_unlikely(c < 0x80 || c > 0x8f))
    1322                 :          0 :                         mp_unreachable();
    1323                 :          0 :                 return c & 0xf;
    1324                 :            :         }
    1325                 :          0 : }
    1326                 :            : 
    1327                 :            : MP_IMPL uint32_t
    1328                 :          0 : mp_sizeof_uint(uint64_t num)
    1329                 :            : {
    1330         [ #  # ]:          0 :         if (num <= 0x7f) {
    1331                 :          0 :                 return 1;
    1332         [ #  # ]:          0 :         } else if (num <= UINT8_MAX) {
    1333                 :          0 :                 return 1 + sizeof(uint8_t);
    1334         [ #  # ]:          0 :         } else if (num <= UINT16_MAX) {
    1335                 :          0 :                 return 1 + sizeof(uint16_t);
    1336         [ #  # ]:          0 :         } else if (num <= UINT32_MAX) {
    1337                 :          0 :                 return 1 + sizeof(uint32_t);
    1338                 :            :         } else {
    1339                 :          0 :                 return 1 + sizeof(uint64_t);
    1340                 :            :         }
    1341                 :          0 : }
    1342                 :            : 
    1343                 :            : MP_IMPL uint32_t
    1344                 :          0 : mp_sizeof_int(int64_t num)
    1345                 :            : {
    1346         [ #  # ]:          0 :         assert(num < 0);
    1347         [ #  # ]:          0 :         if (num >= -0x20) {
    1348                 :          0 :                 return 1;
    1349   [ #  #  #  # ]:          0 :         } else if (num >= INT8_MIN && num <= INT8_MAX) {
    1350                 :          0 :                 return 1 + sizeof(int8_t);
    1351   [ #  #  #  # ]:          0 :         } else if (num >= INT16_MIN && num <= UINT16_MAX) {
    1352                 :          0 :                 return 1 + sizeof(int16_t);
    1353   [ #  #  #  # ]:          0 :         } else if (num >= INT32_MIN && num <= UINT32_MAX) {
    1354                 :          0 :                 return 1 + sizeof(int32_t);
    1355                 :            :         } else {
    1356                 :          0 :                 return 1 + sizeof(int64_t);
    1357                 :            :         }
    1358                 :          0 : }
    1359                 :            : 
    1360                 :            : MP_IMPL ptrdiff_t
    1361                 :          0 : mp_check_uint(const char *cur, const char *end)
    1362                 :            : {
    1363         [ #  # ]:          0 :         assert(cur < end);
    1364         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_UINT);
    1365                 :          0 :         uint8_t c = mp_load_u8(&cur);
    1366                 :          0 :         return mp_parser_hint[c] - (end - cur);
    1367                 :            : }
    1368                 :            : 
    1369                 :            : MP_IMPL ptrdiff_t
    1370                 :          0 : mp_check_int(const char *cur, const char *end)
    1371                 :            : {
    1372         [ #  # ]:          0 :         assert(cur < end);
    1373         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_INT);
    1374                 :          0 :         uint8_t c = mp_load_u8(&cur);
    1375                 :          0 :         return mp_parser_hint[c] - (end - cur);
    1376                 :            : }
    1377                 :            : 
    1378                 :            : MP_IMPL char *
    1379                 :          0 : mp_encode_uint(char *data, uint64_t num)
    1380                 :            : {
    1381         [ #  # ]:          0 :         if (num <= 0x7f) {
    1382                 :          0 :                 return mp_store_u8(data, num);
    1383         [ #  # ]:          0 :         } else if (num <= UINT8_MAX) {
    1384                 :          0 :                 data = mp_store_u8(data, 0xcc);
    1385                 :          0 :                 return mp_store_u8(data, num);
    1386         [ #  # ]:          0 :         } else if (num <= UINT16_MAX) {
    1387                 :          0 :                 data = mp_store_u8(data, 0xcd);
    1388                 :          0 :                 return mp_store_u16(data, num);
    1389         [ #  # ]:          0 :         } else if (num <= UINT32_MAX) {
    1390                 :          0 :                 data = mp_store_u8(data, 0xce);
    1391                 :          0 :                 return mp_store_u32(data, num);
    1392                 :            :         } else {
    1393                 :          0 :                 data = mp_store_u8(data, 0xcf);
    1394                 :          0 :                 return mp_store_u64(data, num);
    1395                 :            :         }
    1396                 :          0 : }
    1397                 :            : 
    1398                 :            : MP_IMPL char *
    1399                 :          0 : mp_encode_int(char *data, int64_t num)
    1400                 :            : {
    1401         [ #  # ]:          0 :         assert(num < 0);
    1402         [ #  # ]:          0 :         if (num >= -0x20) {
    1403                 :          0 :                 return mp_store_u8(data, 0xe0 | num);
    1404         [ #  # ]:          0 :         } else if (num >= INT8_MIN) {
    1405                 :          0 :                 data = mp_store_u8(data, 0xd0);
    1406                 :          0 :                 return mp_store_u8(data, num);
    1407         [ #  # ]:          0 :         } else if (num >= INT16_MIN) {
    1408                 :          0 :                 data = mp_store_u8(data, 0xd1);
    1409                 :          0 :                 return mp_store_u16(data, num);
    1410         [ #  # ]:          0 :         } else if (num >= INT32_MIN) {
    1411                 :          0 :                 data = mp_store_u8(data, 0xd2);
    1412                 :          0 :                 return mp_store_u32(data, num);
    1413                 :            :         } else {
    1414                 :          0 :                 data = mp_store_u8(data, 0xd3);
    1415                 :          0 :                 return mp_store_u64(data, num);
    1416                 :            :         }
    1417                 :          0 : }
    1418                 :            : 
    1419                 :            : MP_IMPL uint64_t
    1420                 :       1650 : mp_decode_uint(const char **data)
    1421                 :            : {
    1422                 :       1650 :         uint8_t c = mp_load_u8(data);
    1423   [ +  +  -  -  :       1650 :         switch (c) {
                      - ]
    1424                 :            :         case 0xcc:
    1425                 :          0 :                 return mp_load_u8(data);
    1426                 :            :         case 0xcd:
    1427                 :         16 :                 return mp_load_u16(data);
    1428                 :            :         case 0xce:
    1429                 :          0 :                 return mp_load_u32(data);
    1430                 :            :         case 0xcf:
    1431                 :          0 :                 return mp_load_u64(data);
    1432                 :            :         default:
    1433         [ +  - ]:       1634 :                 if (mp_unlikely(c > 0x7f))
    1434                 :          0 :                         mp_unreachable();
    1435                 :       1634 :                 return c;
    1436                 :            :         }
    1437                 :       1650 : }
    1438                 :            : 
    1439                 :            : MP_IMPL int
    1440                 :          0 : mp_compare_uint(const char *data_a, const char *data_b)
    1441                 :            : {
    1442                 :          0 :         uint8_t ca = mp_load_u8(&data_a);
    1443                 :          0 :         uint8_t cb = mp_load_u8(&data_b);
    1444                 :            : 
    1445                 :          0 :         int r = ca - cb;
    1446         [ #  # ]:          0 :         if (r != 0)
    1447                 :          0 :                 return r;
    1448                 :            : 
    1449         [ #  # ]:          0 :         if (ca <= 0x7f)
    1450                 :          0 :                 return 0;
    1451                 :            : 
    1452                 :            :         uint64_t a, b;
    1453   [ #  #  #  #  :          0 :         switch (ca & 0x3) {
                      # ]
    1454                 :            :         case 0xcc & 0x3:
    1455                 :          0 :                 a = mp_load_u8(&data_a);
    1456                 :          0 :                 b = mp_load_u8(&data_b);
    1457                 :          0 :                 break;
    1458                 :            :         case 0xcd & 0x3:
    1459                 :          0 :                 a = mp_load_u16(&data_a);
    1460                 :          0 :                 b = mp_load_u16(&data_b);
    1461                 :          0 :                 break;
    1462                 :            :         case 0xce & 0x3:
    1463                 :          0 :                 a = mp_load_u32(&data_a);
    1464                 :          0 :                 b = mp_load_u32(&data_b);
    1465                 :          0 :                 break;
    1466                 :            :         case 0xcf & 0x3:
    1467                 :          0 :                 a = mp_load_u64(&data_a);
    1468                 :          0 :                 b = mp_load_u64(&data_b);
    1469         [ #  # ]:          0 :                 return a < b ? -1 : a > b;
    1470                 :            :                 break;
    1471                 :            :         default:
    1472                 :          0 :                 mp_unreachable();
    1473                 :            :         }
    1474                 :            : 
    1475                 :          0 :         int64_t v = (a - b);
    1476                 :          0 :         return (v > 0) - (v < 0);
    1477                 :          0 : }
    1478                 :            : 
    1479                 :            : MP_IMPL int64_t
    1480                 :          0 : mp_decode_int(const char **data)
    1481                 :            : {
    1482                 :          0 :         uint8_t c = mp_load_u8(data);
    1483   [ #  #  #  #  :          0 :         switch (c) {
                      # ]
    1484                 :            :         case 0xd0:
    1485                 :          0 :                 return (int8_t) mp_load_u8(data);
    1486                 :            :         case 0xd1:
    1487                 :          0 :                 return (int16_t) mp_load_u16(data);
    1488                 :            :         case 0xd2:
    1489                 :          0 :                 return (int32_t) mp_load_u32(data);
    1490                 :            :         case 0xd3:
    1491                 :          0 :                 return (int64_t) mp_load_u64(data);
    1492                 :            :         default:
    1493         [ #  # ]:          0 :                 if (mp_unlikely(c < 0xe0))
    1494                 :          0 :                         mp_unreachable();
    1495                 :          0 :                 return (int8_t) (c);
    1496                 :            :         }
    1497                 :          0 : }
    1498                 :            : 
    1499                 :            : MP_IMPL uint32_t
    1500                 :          0 : mp_sizeof_float(float num)
    1501                 :            : {
    1502                 :          0 :         (void) num;
    1503                 :          0 :         return 1 + sizeof(float);
    1504                 :            : }
    1505                 :            : 
    1506                 :            : MP_IMPL uint32_t
    1507                 :          0 : mp_sizeof_double(double num)
    1508                 :            : {
    1509                 :          0 :         (void) num;
    1510                 :          0 :         return 1 + sizeof(double);
    1511                 :            : }
    1512                 :            : 
    1513                 :            : MP_IMPL ptrdiff_t
    1514                 :          0 : mp_check_float(const char *cur, const char *end)
    1515                 :            : {
    1516         [ #  # ]:          0 :         assert(cur < end);
    1517         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_FLOAT);
    1518                 :          0 :         return 1 + sizeof(float) - (end - cur);
    1519                 :            : }
    1520                 :            : 
    1521                 :            : MP_IMPL ptrdiff_t
    1522                 :          0 : mp_check_double(const char *cur, const char *end)
    1523                 :            : {
    1524         [ #  # ]:          0 :         assert(cur < end);
    1525         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_DOUBLE);
    1526                 :          0 :         return 1 + sizeof(double) - (end - cur);
    1527                 :            : }
    1528                 :            : 
    1529                 :            : MP_IMPL char *
    1530                 :          0 : mp_encode_float(char *data, float num)
    1531                 :            : {
    1532                 :          0 :         data = mp_store_u8(data, 0xca);
    1533                 :          0 :         return mp_store_float(data, num);
    1534                 :            : }
    1535                 :            : 
    1536                 :            : MP_IMPL char *
    1537                 :          0 : mp_encode_double(char *data, double num)
    1538                 :            : {
    1539                 :          0 :         data = mp_store_u8(data, 0xcb);
    1540                 :          0 :         return mp_store_double(data, num);
    1541                 :            : }
    1542                 :            : 
    1543                 :            : MP_IMPL float
    1544                 :          0 : mp_decode_float(const char **data)
    1545                 :            : {
    1546                 :          0 :         uint8_t c = mp_load_u8(data);
    1547         [ #  # ]:          0 :         assert(c == 0xca);
    1548                 :          0 :         (void) c;
    1549                 :          0 :         return mp_load_float(data);
    1550                 :            : }
    1551                 :            : 
    1552                 :            : MP_IMPL double
    1553                 :          0 : mp_decode_double(const char **data)
    1554                 :            : {
    1555                 :          0 :         uint8_t c = mp_load_u8(data);
    1556         [ #  # ]:          0 :         assert(c == 0xcb);
    1557                 :          0 :         (void) c;
    1558                 :          0 :         return mp_load_double(data);
    1559                 :            : }
    1560                 :            : 
    1561                 :            : MP_IMPL uint32_t
    1562                 :          0 : mp_sizeof_strl(uint32_t len)
    1563                 :            : {
    1564         [ #  # ]:          0 :         if (len <= 31) {
    1565                 :          0 :                 return 1;
    1566         [ #  # ]:          0 :         } else if (len <= UINT8_MAX) {
    1567                 :          0 :                 return 1 + sizeof(uint8_t);
    1568         [ #  # ]:          0 :         } else if (len <= UINT16_MAX) {
    1569                 :          0 :                 return 1 + sizeof(uint16_t);
    1570                 :            :         } else {
    1571                 :          0 :                 return 1 + sizeof(uint32_t);
    1572                 :            :         }
    1573                 :          0 : }
    1574                 :            : 
    1575                 :            : MP_IMPL uint32_t
    1576                 :          0 : mp_sizeof_str(uint32_t len)
    1577                 :            : {
    1578                 :          0 :         return mp_sizeof_strl(len) + len;
    1579                 :            : }
    1580                 :            : 
    1581                 :            : MP_IMPL uint32_t
    1582                 :          0 : mp_sizeof_binl(uint32_t len)
    1583                 :            : {
    1584         [ #  # ]:          0 :         if (len <= UINT8_MAX) {
    1585                 :          0 :                 return 1 + sizeof(uint8_t);
    1586         [ #  # ]:          0 :         } else if (len <= UINT16_MAX) {
    1587                 :          0 :                 return 1 + sizeof(uint16_t);
    1588                 :            :         } else {
    1589                 :          0 :                 return 1 + sizeof(uint32_t);
    1590                 :            :         }
    1591                 :          0 : }
    1592                 :            : 
    1593                 :            : MP_IMPL uint32_t
    1594                 :          0 : mp_sizeof_bin(uint32_t len)
    1595                 :            : {
    1596                 :          0 :         return mp_sizeof_binl(len) + len;
    1597                 :            : }
    1598                 :            : 
    1599                 :            : MP_IMPL char *
    1600                 :       2136 : mp_encode_strl(char *data, uint32_t len)
    1601                 :            : {
    1602         [ +  + ]:       2136 :         if (len <= 31) {
    1603                 :       2032 :                 return mp_store_u8(data, 0xa0 | (uint8_t) len);
    1604         [ +  - ]:        104 :         } else if (len <= UINT8_MAX) {
    1605                 :        104 :                 data = mp_store_u8(data, 0xd9);
    1606                 :        104 :                 return mp_store_u8(data, len);
    1607         [ #  # ]:          0 :         } else if (len <= UINT16_MAX) {
    1608                 :          0 :                 data = mp_store_u8(data, 0xda);
    1609                 :          0 :                 return mp_store_u16(data, len);
    1610                 :            :         } else {
    1611                 :          0 :                 data = mp_store_u8(data, 0xdb);
    1612                 :          0 :                 return mp_store_u32(data, len);
    1613                 :            :         }
    1614                 :       2136 : }
    1615                 :            : 
    1616                 :            : MP_IMPL char *
    1617                 :       2136 : mp_encode_str(char *data, const char *str, uint32_t len)
    1618                 :            : {
    1619                 :       2136 :         data = mp_encode_strl(data, len);
    1620                 :       2136 :         memcpy(data, str, len);
    1621                 :       2136 :         return data + len;
    1622                 :            : }
    1623                 :            : 
    1624                 :            : MP_IMPL char *
    1625                 :          0 : mp_encode_binl(char *data, uint32_t len)
    1626                 :            : {
    1627         [ #  # ]:          0 :         if (len <= UINT8_MAX) {
    1628                 :          0 :                 data = mp_store_u8(data, 0xc4);
    1629                 :          0 :                 return mp_store_u8(data, len);
    1630         [ #  # ]:          0 :         } else if (len <= UINT16_MAX) {
    1631                 :          0 :                 data = mp_store_u8(data, 0xc5);
    1632                 :          0 :                 return mp_store_u16(data, len);
    1633                 :            :         } else {
    1634                 :          0 :                 data = mp_store_u8(data, 0xc6);
    1635                 :          0 :                 return mp_store_u32(data, len);
    1636                 :            :         }
    1637                 :          0 : }
    1638                 :            : 
    1639                 :            : MP_IMPL char *
    1640                 :          0 : mp_encode_bin(char *data, const char *str, uint32_t len)
    1641                 :            : {
    1642                 :          0 :         data = mp_encode_binl(data, len);
    1643                 :          0 :         memcpy(data, str, len);
    1644                 :          0 :         return data + len;
    1645                 :            : }
    1646                 :            : 
    1647                 :            : MP_IMPL ptrdiff_t
    1648                 :          0 : mp_check_strl(const char *cur, const char *end)
    1649                 :            : {
    1650         [ #  # ]:          0 :         assert(cur < end);
    1651         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_STR);
    1652                 :            : 
    1653                 :          0 :         uint8_t c = mp_load_u8(&cur);
    1654         [ #  # ]:          0 :         if (mp_likely(c & ~0x1f) == 0xa0)
    1655                 :          0 :                 return cur - end;
    1656                 :            : 
    1657         [ #  # ]:          0 :         assert(c >= 0xd9 && c <= 0xdb); /* must be checked above by mp_typeof */
    1658                 :          0 :         uint32_t hsize = 1U << (c & 0x3) >> 1; /* 0xd9->1, 0xda->2, 0xdb->4 */
    1659                 :          0 :         return hsize - (end - cur);
    1660                 :          0 : }
    1661                 :            : 
    1662                 :            : MP_IMPL ptrdiff_t
    1663                 :          0 : mp_check_binl(const char *cur, const char *end)
    1664                 :            : {
    1665                 :          0 :         uint8_t c = mp_load_u8(&cur);
    1666         [ #  # ]:          0 :         assert(cur < end);
    1667         [ #  # ]:          0 :         assert(mp_typeof(c) == MP_BIN);
    1668                 :            : 
    1669         [ #  # ]:          0 :         assert(c >= 0xc4 && c <= 0xc6); /* must be checked above by mp_typeof */
    1670                 :          0 :         uint32_t hsize = 1U << (c & 0x3); /* 0xc4->1, 0xc5->2, 0xc6->4 */
    1671                 :          0 :         return hsize - (end - cur);
    1672                 :            : }
    1673                 :            : 
    1674                 :            : MP_IMPL uint32_t
    1675                 :         36 : mp_decode_strl(const char **data)
    1676                 :            : {
    1677                 :         36 :         uint8_t c = mp_load_u8(data);
    1678   [ -  +  +  - ]:         36 :         switch (c) {
    1679                 :            :         case 0xd9:
    1680                 :         24 :                 return mp_load_u8(data);
    1681                 :            :         case 0xda:
    1682                 :          0 :                 return mp_load_u16(data);
    1683                 :            :         case 0xdb:
    1684                 :          0 :                 return mp_load_u32(data);
    1685                 :            :         default:
    1686   [ -  +  +  - ]:         12 :                 if (mp_unlikely(c < 0xa0 || c > 0xbf))
    1687                 :          0 :                         mp_unreachable();
    1688                 :         12 :                 return c & 0x1f;
    1689                 :            :         }
    1690                 :         36 : }
    1691                 :            : 
    1692                 :            : MP_IMPL const char *
    1693                 :         36 : mp_decode_str(const char **data, uint32_t *len)
    1694                 :            : {
    1695         [ +  - ]:         36 :         assert(len != NULL);
    1696                 :            : 
    1697                 :         36 :         *len = mp_decode_strl(data);
    1698                 :         36 :         const char *str = *data;
    1699                 :         36 :         *data += *len;
    1700                 :         36 :         return str;
    1701                 :            : }
    1702                 :            : 
    1703                 :            : MP_IMPL uint32_t
    1704                 :          0 : mp_decode_binl(const char **data)
    1705                 :            : {
    1706                 :          0 :         uint8_t c = mp_load_u8(data);
    1707                 :            : 
    1708   [ #  #  #  # ]:          0 :         switch (c) {
    1709                 :            :         case 0xc4:
    1710                 :          0 :                 return mp_load_u8(data);
    1711                 :            :         case 0xc5:
    1712                 :          0 :                 return mp_load_u16(data);
    1713                 :            :         case 0xc6:
    1714                 :          0 :                 return mp_load_u32(data);
    1715                 :            :         default:
    1716                 :          0 :                 mp_unreachable();
    1717                 :            :         }
    1718                 :          0 : }
    1719                 :            : 
    1720                 :            : MP_IMPL const char *
    1721                 :          0 : mp_decode_bin(const char **data, uint32_t *len)
    1722                 :            : {
    1723         [ #  # ]:          0 :         assert(len != NULL);
    1724                 :            : 
    1725                 :          0 :         *len = mp_decode_binl(data);
    1726                 :          0 :         const char *str = *data;
    1727                 :          0 :         *data += *len;
    1728                 :          0 :         return str;
    1729                 :            : }
    1730                 :            : 
    1731                 :            : MP_IMPL uint32_t
    1732                 :          0 : mp_decode_strbinl(const char **data)
    1733                 :            : {
    1734                 :          0 :         uint8_t c = mp_load_u8(data);
    1735                 :            : 
    1736   [ #  #  #  #  :          0 :         switch (c) {
                #  #  # ]
    1737                 :            :         case 0xd9:
    1738                 :          0 :                 return mp_load_u8(data);
    1739                 :            :         case 0xda:
    1740                 :          0 :                 return mp_load_u16(data);
    1741                 :            :         case 0xdb:
    1742                 :          0 :                 return mp_load_u32(data);
    1743                 :            :         case 0xc4:
    1744                 :          0 :                 return mp_load_u8(data);
    1745                 :            :         case 0xc5:
    1746                 :          0 :                 return mp_load_u16(data);
    1747                 :            :         case 0xc6:
    1748                 :          0 :                 return mp_load_u32(data);
    1749                 :            :         default:
    1750   [ #  #  #  # ]:          0 :                 if (mp_unlikely(c < 0xa0 || c > 0xbf))
    1751                 :          0 :                         mp_unreachable();
    1752                 :          0 :                 return c & 0x1f;
    1753                 :            :         }
    1754                 :          0 : }
    1755                 :            : 
    1756                 :            : MP_IMPL const char *
    1757                 :          0 : mp_decode_strbin(const char **data, uint32_t *len)
    1758                 :            : {
    1759         [ #  # ]:          0 :         assert(len != NULL);
    1760                 :            : 
    1761                 :          0 :         *len = mp_decode_strbinl(data);
    1762                 :          0 :         const char *str = *data;
    1763                 :          0 :         *data += *len;
    1764                 :          0 :         return str;
    1765                 :            : }
    1766                 :            : 
    1767                 :            : MP_IMPL uint32_t
    1768                 :          0 : mp_sizeof_nil()
    1769                 :            : {
    1770                 :          0 :         return 1;
    1771                 :            : }
    1772                 :            : 
    1773                 :            : MP_IMPL char *
    1774                 :          0 : mp_encode_nil(char *data)
    1775                 :            : {
    1776                 :          0 :         return mp_store_u8(data, 0xc0);
    1777                 :            : }
    1778                 :            : 
    1779                 :            : MP_IMPL ptrdiff_t
    1780                 :          0 : mp_check_nil(const char *cur, const char *end)
    1781                 :            : {
    1782         [ #  # ]:          0 :         assert(cur < end);
    1783         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_NIL);
    1784                 :          0 :         return 1 - (end - cur);
    1785                 :            : }
    1786                 :            : 
    1787                 :            : MP_IMPL void
    1788                 :          0 : mp_decode_nil(const char **data)
    1789                 :            : {
    1790                 :          0 :         uint8_t c = mp_load_u8(data);
    1791         [ #  # ]:          0 :         assert(c == 0xc0);
    1792                 :          0 :         (void) c;
    1793                 :          0 : }
    1794                 :            : 
    1795                 :            : MP_IMPL uint32_t
    1796                 :          0 : mp_sizeof_bool(bool val)
    1797                 :            : {
    1798                 :          0 :         (void) val;
    1799                 :          0 :         return 1;
    1800                 :            : }
    1801                 :            : 
    1802                 :            : MP_IMPL char *
    1803                 :          0 : mp_encode_bool(char *data, bool val)
    1804                 :            : {
    1805                 :          0 :         return mp_store_u8(data, 0xc2 | (val & 1));
    1806                 :            : }
    1807                 :            : 
    1808                 :            : MP_IMPL ptrdiff_t
    1809                 :          0 : mp_check_bool(const char *cur, const char *end)
    1810                 :            : {
    1811         [ #  # ]:          0 :         assert(cur < end);
    1812         [ #  # ]:          0 :         assert(mp_typeof(*cur) == MP_BOOL);
    1813                 :          0 :         return 1 - (end - cur);
    1814                 :            : }
    1815                 :            : 
    1816                 :            : MP_IMPL bool
    1817                 :          0 : mp_decode_bool(const char **data)
    1818                 :            : {
    1819                 :          0 :         uint8_t c = mp_load_u8(data);
    1820      [ #  #  # ]:          0 :         switch (c) {
    1821                 :            :         case 0xc3:
    1822                 :          0 :                 return true;
    1823                 :            :         case 0xc2:
    1824                 :          0 :                 return false;
    1825                 :            :         default:
    1826                 :          0 :                 mp_unreachable();
    1827                 :            :         }
    1828                 :          0 : }
    1829                 :            : 
    1830                 :            : MP_IMPL int
    1831                 :          0 : mp_read_int32(const char **data, int32_t *ret)
    1832                 :            : {
    1833                 :            :         uint32_t uval;
    1834                 :          0 :         const char *p = *data;
    1835                 :          0 :         uint8_t c = mp_load_u8(&p);
    1836   [ #  #  #  #  :          0 :         switch (c) {
                #  #  # ]
    1837                 :            :         case 0xd0:
    1838                 :          0 :                 *ret = (int8_t) mp_load_u8(&p);
    1839                 :          0 :                 break;
    1840                 :            :         case 0xd1:
    1841                 :          0 :                 *ret = (int16_t) mp_load_u16(&p);
    1842                 :          0 :                 break;
    1843                 :            :         case 0xd2:
    1844                 :          0 :                 *ret = (int32_t) mp_load_u32(&p);
    1845                 :          0 :                 break;
    1846                 :            :         case 0xcc:
    1847                 :          0 :                 *ret = mp_load_u8(&p);
    1848                 :          0 :                 break;
    1849                 :            :         case 0xcd:
    1850                 :          0 :                 *ret = mp_load_u16(&p);
    1851                 :          0 :                 break;
    1852                 :            :         case 0xce:
    1853                 :          0 :                 uval = mp_load_u32(&p);
    1854         [ #  # ]:          0 :                 if (mp_unlikely(uval > INT32_MAX))
    1855                 :          0 :                         return -1;
    1856                 :          0 :                 *ret = uval;
    1857                 :          0 :                 break;
    1858                 :            :         default:
    1859   [ #  #  #  # ]:          0 :                 if (mp_unlikely(c < 0xe0 && c > 0x7f))
    1860                 :          0 :                         return -1;
    1861                 :          0 :                 *ret = (int8_t) c;
    1862                 :          0 :                 break;
    1863                 :            :         }
    1864                 :          0 :         *data = p;
    1865                 :          0 :         return 0;
    1866                 :          0 : }
    1867                 :            : 
    1868                 :            : MP_IMPL int
    1869                 :          0 : mp_read_int64(const char **data, int64_t *ret)
    1870                 :            : {
    1871                 :            :         uint64_t uval;
    1872                 :          0 :         const char *p = *data;
    1873                 :          0 :         uint8_t c = mp_load_u8(&p);
    1874   [ #  #  #  #  :          0 :         switch (c) {
             #  #  #  #  
                      # ]
    1875                 :            :         case 0xd0:
    1876                 :          0 :                 *ret = (int8_t) mp_load_u8(&p);
    1877                 :          0 :                 break;
    1878                 :            :         case 0xd1:
    1879                 :          0 :                 *ret = (int16_t) mp_load_u16(&p);
    1880                 :          0 :                 break;
    1881                 :            :         case 0xd2:
    1882                 :          0 :                 *ret = (int32_t) mp_load_u32(&p);
    1883                 :          0 :                 break;
    1884                 :            :         case 0xd3:
    1885                 :          0 :                 *ret = (int64_t) mp_load_u64(&p);
    1886                 :          0 :                 break;
    1887                 :            :         case 0xcc:
    1888                 :          0 :                 *ret = mp_load_u8(&p);
    1889                 :          0 :                 break;
    1890                 :            :         case 0xcd:
    1891                 :          0 :                 *ret = mp_load_u16(&p);
    1892                 :          0 :                 break;
    1893                 :            :         case 0xce:
    1894                 :          0 :                 *ret = mp_load_u32(&p);
    1895                 :          0 :                 break;
    1896                 :            :         case 0xcf:
    1897                 :          0 :                 uval = mp_load_u64(&p);
    1898         [ #  # ]:          0 :                 if (uval > INT64_MAX)
    1899                 :          0 :                         return -1;
    1900                 :          0 :                 *ret = uval;
    1901                 :          0 :                 break;
    1902                 :            :         default:
    1903   [ #  #  #  # ]:          0 :                 if (mp_unlikely(c < 0xe0 && c > 0x7f))
    1904                 :          0 :                         return -1;
    1905                 :          0 :                 *ret = (int8_t) c;
    1906                 :          0 :                 break;
    1907                 :            :         }
    1908                 :          0 :         *data = p;
    1909                 :          0 :         return 0;
    1910                 :          0 : }
    1911                 :            : 
    1912                 :            : MP_IMPL int
    1913                 :          0 : mp_read_double(const char **data, double *ret)
    1914                 :            : {
    1915                 :            :         int64_t ival;
    1916                 :            :         uint64_t uval;
    1917                 :            :         double val;
    1918                 :          0 :         const char *p = *data;
    1919                 :          0 :         uint8_t c = mp_load_u8(&p);
    1920   [ #  #  #  #  :          0 :         switch (c) {
          #  #  #  #  #  
                   #  # ]
    1921                 :            :         case 0xd0:
    1922                 :          0 :                 *ret = (int8_t) mp_load_u8(&p);
    1923                 :          0 :                 break;
    1924                 :            :         case 0xd1:
    1925                 :          0 :                 *ret = (int16_t) mp_load_u16(&p);
    1926                 :          0 :                 break;
    1927                 :            :         case 0xd2:
    1928                 :          0 :                 *ret = (int32_t) mp_load_u32(&p);
    1929                 :          0 :                 break;
    1930                 :            :         case 0xd3:
    1931                 :          0 :                 val = ival = (int64_t) mp_load_u64(&p);
    1932         [ #  # ]:          0 :                 if ((int64_t)val != ival)
    1933                 :          0 :                         return -1;
    1934                 :          0 :                 *ret = val;
    1935                 :          0 :                 break;
    1936                 :            :         case 0xcc:
    1937                 :          0 :                 *ret = mp_load_u8(&p);
    1938                 :          0 :                 break;
    1939                 :            :         case 0xcd:
    1940                 :          0 :                 *ret = mp_load_u16(&p);
    1941                 :          0 :                 break;
    1942                 :            :         case 0xce:
    1943                 :          0 :                 *ret = mp_load_u32(&p);
    1944                 :          0 :                 break;
    1945                 :            :         case 0xcf:
    1946                 :          0 :                 val = uval = mp_load_u64(&p);
    1947         [ #  # ]:          0 :                 if ((uint64_t)val != uval)
    1948                 :          0 :                         return -1;
    1949                 :          0 :                 *ret = val;
    1950                 :          0 :                 break;
    1951                 :            :         case 0xca:
    1952                 :          0 :                 *ret = mp_load_float(&p);
    1953                 :          0 :                 break;
    1954                 :            :         case 0xcb:
    1955                 :          0 :                 *ret = mp_load_double(&p);
    1956                 :          0 :                 break;
    1957                 :            :         default:
    1958   [ #  #  #  # ]:          0 :                 if (mp_unlikely(c < 0xe0 && c > 0x7f))
    1959                 :          0 :                         return -1;
    1960                 :          0 :                 *ret = (int8_t) c;
    1961                 :          0 :                 break;
    1962                 :            :         }
    1963                 :          0 :         *data = p;
    1964                 :          0 :         return 0;
    1965                 :          0 : }
    1966                 :            : 
    1967                 :            : /** See mp_parser_hint */
    1968                 :            : enum {
    1969                 :            :         MP_HINT = -32,
    1970                 :            :         MP_HINT_STR_8 = MP_HINT,
    1971                 :            :         MP_HINT_STR_16 = MP_HINT - 1,
    1972                 :            :         MP_HINT_STR_32 = MP_HINT - 2,
    1973                 :            :         MP_HINT_ARRAY_16 = MP_HINT - 3,
    1974                 :            :         MP_HINT_ARRAY_32 = MP_HINT - 4,
    1975                 :            :         MP_HINT_MAP_16 = MP_HINT - 5,
    1976                 :            :         MP_HINT_MAP_32 = MP_HINT - 6,
    1977                 :            :         MP_HINT_EXT_8 = MP_HINT - 7,
    1978                 :            :         MP_HINT_EXT_16 = MP_HINT - 8,
    1979                 :            :         MP_HINT_EXT_32 = MP_HINT - 9
    1980                 :            : };
    1981                 :            : 
    1982                 :            : MP_PROTO void
    1983                 :            : mp_next_slowpath(const char **data, int64_t k);
    1984                 :            : 
    1985                 :            : MP_IMPL void
    1986                 :          0 : mp_next_slowpath(const char **data, int64_t k)
    1987                 :            : {
    1988         [ #  # ]:          0 :         for (; k > 0; k--) {
    1989                 :          0 :                 uint8_t c = mp_load_u8(data);
    1990                 :          0 :                 int l = mp_parser_hint[c];
    1991         [ #  # ]:          0 :                 if (mp_likely(l >= 0)) {
    1992                 :          0 :                         *data += l;
    1993                 :          0 :                         continue;
    1994         [ #  # ]:          0 :                 } else if (mp_likely(l > MP_HINT)) {
    1995                 :          0 :                         k -= l;
    1996                 :          0 :                         continue;
    1997                 :            :                 }
    1998                 :            : 
    1999                 :            :                 uint32_t len;
    2000   [ #  #  #  #  :          0 :                 switch (l) {
          #  #  #  #  #  
                   #  # ]
    2001                 :            :                 case MP_HINT_STR_8:
    2002                 :            :                         /* MP_STR (8) */
    2003                 :          0 :                         len = mp_load_u8(data);
    2004                 :          0 :                         *data += len;
    2005                 :          0 :                         break;
    2006                 :            :                 case MP_HINT_STR_16:
    2007                 :            :                         /* MP_STR (16) */
    2008                 :          0 :                         len = mp_load_u16(data);
    2009                 :          0 :                         *data += len;
    2010                 :          0 :                         break;
    2011                 :            :                 case MP_HINT_STR_32:
    2012                 :            :                         /* MP_STR (32) */
    2013                 :          0 :                         len = mp_load_u32(data);
    2014                 :          0 :                         *data += len;
    2015                 :          0 :                         break;
    2016                 :            :                 case MP_HINT_ARRAY_16:
    2017                 :            :                         /* MP_ARRAY (16) */
    2018                 :          0 :                         k += mp_load_u16(data);
    2019                 :          0 :                         break;
    2020                 :            :                 case MP_HINT_ARRAY_32:
    2021                 :            :                         /* MP_ARRAY (32) */
    2022                 :          0 :                         k += mp_load_u32(data);
    2023                 :          0 :                         break;
    2024                 :            :                 case MP_HINT_MAP_16:
    2025                 :            :                         /* MP_MAP (16) */
    2026                 :          0 :                         k += 2 * mp_load_u16(data);
    2027                 :          0 :                         break;
    2028                 :            :                 case MP_HINT_MAP_32:
    2029                 :            :                         /* MP_MAP (32) */
    2030                 :          0 :                         k += 2 * mp_load_u32(data);
    2031                 :          0 :                         break;
    2032                 :            :                 case MP_HINT_EXT_8:
    2033                 :            :                         /* MP_EXT (8) */
    2034                 :          0 :                         len = mp_load_u8(data);
    2035                 :          0 :                         mp_load_u8(data);
    2036                 :          0 :                         *data += len;
    2037                 :          0 :                         break;
    2038                 :            :                 case MP_HINT_EXT_16:
    2039                 :            :                         /* MP_EXT (16) */
    2040                 :          0 :                         len = mp_load_u16(data);
    2041                 :          0 :                         mp_load_u8(data);
    2042                 :          0 :                         *data += len;
    2043                 :          0 :                         break;
    2044                 :            :                 case MP_HINT_EXT_32:
    2045                 :            :                         /* MP_EXT (32) */
    2046                 :          0 :                         len = mp_load_u32(data);
    2047                 :          0 :                         mp_load_u8(data);
    2048                 :          0 :                         *data += len;
    2049                 :          0 :                         break;
    2050                 :            :                 default:
    2051                 :          0 :                         mp_unreachable();
    2052                 :            :                 }
    2053                 :          0 :         }
    2054                 :          0 : }
    2055                 :            : 
    2056                 :            : MP_IMPL void
    2057                 :          0 : mp_next(const char **data)
    2058                 :            : {
    2059                 :          0 :         int64_t k = 1;
    2060         [ #  # ]:          0 :         for (; k > 0; k--) {
    2061                 :          0 :                 uint8_t c = mp_load_u8(data);
    2062                 :          0 :                 int l = mp_parser_hint[c];
    2063         [ #  # ]:          0 :                 if (mp_likely(l >= 0)) {
    2064                 :          0 :                         *data += l;
    2065                 :          0 :                         continue;
    2066         [ #  # ]:          0 :                 } else if (mp_likely(c == 0xd9)){
    2067                 :            :                         /* MP_STR (8) */
    2068                 :          0 :                         uint8_t len = mp_load_u8(data);
    2069                 :          0 :                         *data += len;
    2070                 :          0 :                         continue;
    2071         [ #  # ]:          0 :                 } else if (l > MP_HINT) {
    2072                 :          0 :                         k -= l;
    2073                 :          0 :                         continue;
    2074                 :            :                 } else {
    2075                 :          0 :                         *data -= sizeof(uint8_t);
    2076                 :          0 :                         return mp_next_slowpath(data, k);
    2077                 :            :                 }
    2078                 :            :         }
    2079                 :          0 : }
    2080                 :            : 
    2081                 :            : MP_IMPL int
    2082                 :          0 : mp_check(const char **data, const char *end)
    2083                 :            : {
    2084                 :            : #define MP_CHECK_LEN(_l) \
    2085                 :            :         if (mp_unlikely((size_t)(end - *data) < (size_t)(_l))) \
    2086                 :            :                 return 1;
    2087                 :            : 
    2088                 :            :         int64_t k;
    2089         [ #  # ]:          0 :         for (k = 1; k > 0; k--) {
    2090         [ #  # ]:          0 :                 MP_CHECK_LEN(1);
    2091                 :          0 :                 uint8_t c = mp_load_u8(data);
    2092                 :          0 :                 int l = mp_parser_hint[c];
    2093         [ #  # ]:          0 :                 if (mp_likely(l >= 0)) {
    2094         [ #  # ]:          0 :                         MP_CHECK_LEN(l);
    2095                 :          0 :                         *data += l;
    2096                 :          0 :                         continue;
    2097         [ #  # ]:          0 :                 } else if (mp_likely(l > MP_HINT)) {
    2098                 :          0 :                         k -= l;
    2099                 :          0 :                         continue;
    2100                 :            :                 }
    2101                 :            : 
    2102                 :            :                 uint32_t len;
    2103   [ #  #  #  #  :          0 :                 switch (l) {
          #  #  #  #  #  
                   #  # ]
    2104                 :            :                 case MP_HINT_STR_8:
    2105                 :            :                         /* MP_STR (8) */
    2106         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint8_t));
    2107                 :          0 :                         len = mp_load_u8(data);
    2108         [ #  # ]:          0 :                         MP_CHECK_LEN(len);
    2109                 :          0 :                         *data += len;
    2110                 :          0 :                         break;
    2111                 :            :                 case MP_HINT_STR_16:
    2112                 :            :                         /* MP_STR (16) */
    2113         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint16_t));
    2114                 :          0 :                         len = mp_load_u16(data);
    2115         [ #  # ]:          0 :                         MP_CHECK_LEN(len);
    2116                 :          0 :                         *data += len;
    2117                 :          0 :                         break;
    2118                 :            :                 case MP_HINT_STR_32:
    2119                 :            :                         /* MP_STR (32) */
    2120         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint32_t))
    2121                 :          0 :                         len = mp_load_u32(data);
    2122         [ #  # ]:          0 :                         MP_CHECK_LEN(len);
    2123                 :          0 :                         *data += len;
    2124                 :          0 :                         break;
    2125                 :            :                 case MP_HINT_ARRAY_16:
    2126                 :            :                         /* MP_ARRAY (16) */
    2127         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint16_t));
    2128                 :          0 :                         k += mp_load_u16(data);
    2129                 :          0 :                         break;
    2130                 :            :                 case MP_HINT_ARRAY_32:
    2131                 :            :                         /* MP_ARRAY (32) */
    2132         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint32_t));
    2133                 :          0 :                         k += mp_load_u32(data);
    2134                 :          0 :                         break;
    2135                 :            :                 case MP_HINT_MAP_16:
    2136                 :            :                         /* MP_MAP (16) */
    2137         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint16_t));
    2138                 :          0 :                         k += 2 * mp_load_u16(data);
    2139                 :          0 :                         break;
    2140                 :            :                 case MP_HINT_MAP_32:
    2141                 :            :                         /* MP_MAP (32) */
    2142         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint32_t));
    2143                 :          0 :                         k += 2 * mp_load_u32(data);
    2144                 :          0 :                         break;
    2145                 :            :                 case MP_HINT_EXT_8:
    2146                 :            :                         /* MP_EXT (8) */
    2147         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint8_t) + sizeof(uint8_t));
    2148                 :          0 :                         len = mp_load_u8(data);
    2149                 :          0 :                         mp_load_u8(data);
    2150         [ #  # ]:          0 :                         MP_CHECK_LEN(len);
    2151                 :          0 :                         *data += len;
    2152                 :          0 :                         break;
    2153                 :            :                 case MP_HINT_EXT_16:
    2154                 :            :                         /* MP_EXT (16) */
    2155         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint16_t) + sizeof(uint8_t));
    2156                 :          0 :                         len = mp_load_u16(data);
    2157                 :          0 :                         mp_load_u8(data);
    2158         [ #  # ]:          0 :                         MP_CHECK_LEN(len);
    2159                 :          0 :                         *data += len;
    2160                 :          0 :                         break;
    2161                 :            :                 case MP_HINT_EXT_32:
    2162                 :            :                         /* MP_EXT (32) */
    2163         [ #  # ]:          0 :                         MP_CHECK_LEN(sizeof(uint32_t) + sizeof(uint8_t));
    2164                 :          0 :                         len = mp_load_u32(data);
    2165                 :          0 :                         mp_load_u8(data);
    2166         [ #  # ]:          0 :                         MP_CHECK_LEN(len);
    2167                 :          0 :                         *data += len;
    2168                 :          0 :                         break;
    2169                 :            :                 default:
    2170                 :          0 :                         mp_unreachable();
    2171                 :            :                 }
    2172                 :          0 :         }
    2173                 :            : 
    2174         [ #  # ]:          0 :         assert(*data <= end);
    2175                 :            : #undef MP_CHECK_LEN
    2176                 :          0 :         return 0;
    2177                 :          0 : }
    2178                 :            : 
    2179                 :            : /** \endcond */
    2180                 :            : 
    2181                 :            : /*
    2182                 :            :  * }}}
    2183                 :            :  */
    2184                 :            : 
    2185                 :            : #if defined(__cplusplus)
    2186                 :            : } /* extern "C" */
    2187                 :            : #endif /* defined(__cplusplus) */
    2188                 :            : 
    2189                 :            : #undef MP_LIBRARY
    2190                 :            : #undef MP_PROTO
    2191                 :            : #undef MP_IMPL
    2192                 :            : #undef MP_ALWAYSINLINE
    2193                 :            : #undef MP_GCC_VERSION
    2194                 :            : 
    2195                 :            : #endif /* MSGPUCK_H_INCLUDED */

Generated by: LCOV version 1.15