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 */
|