lwtarantool 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +84 -0
  3. data/ext/lwtarantool/conn.c +314 -0
  4. data/ext/lwtarantool/depend +23 -0
  5. data/ext/lwtarantool/errors.c +24 -0
  6. data/ext/lwtarantool/extconf.rb +8 -0
  7. data/ext/lwtarantool/lwtarantool.c +12 -0
  8. data/ext/lwtarantool/lwtarantool.h +38 -0
  9. data/ext/lwtarantool/request.c +124 -0
  10. data/ext/lwtarantool/vendor/msgpuck/CMakeLists.txt +73 -0
  11. data/ext/lwtarantool/vendor/msgpuck/hints.c +674 -0
  12. data/ext/lwtarantool/vendor/msgpuck/msgpuck.c +375 -0
  13. data/ext/lwtarantool/vendor/msgpuck/msgpuck.h +2195 -0
  14. data/ext/lwtarantool/vendor/msgpuck/test/CMakeLists.txt +25 -0
  15. data/ext/lwtarantool/vendor/msgpuck/test/msgpuck.c +1126 -0
  16. data/ext/lwtarantool/vendor/msgpuck/test/test.c +105 -0
  17. data/ext/lwtarantool/vendor/msgpuck/test/test.h +123 -0
  18. data/ext/lwtarantool/vendor/tarantool-c/CMakeLists.txt +89 -0
  19. data/ext/lwtarantool/vendor/tarantool-c/cmake/FindMsgPuck.cmake +18 -0
  20. data/ext/lwtarantool/vendor/tarantool-c/cmake/FindSphinx.cmake +10 -0
  21. data/ext/lwtarantool/vendor/tarantool-c/doc/CMakeLists.txt +15 -0
  22. data/ext/lwtarantool/vendor/tarantool-c/doc/source/example.c +340 -0
  23. data/ext/lwtarantool/vendor/tarantool-c/include/CMakeLists.txt +6 -0
  24. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tarantool.h +67 -0
  25. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_auth.h +72 -0
  26. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_buf.h +88 -0
  27. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_call.h +83 -0
  28. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_delete.h +52 -0
  29. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_execute.h +24 -0
  30. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_insert.h +62 -0
  31. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_io.h +67 -0
  32. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_iob.h +62 -0
  33. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_iter.h +301 -0
  34. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_mem.h +102 -0
  35. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_net.h +242 -0
  36. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_object.h +248 -0
  37. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_opt.h +138 -0
  38. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_ping.h +49 -0
  39. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_proto.h +295 -0
  40. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_reply.h +204 -0
  41. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_request.h +377 -0
  42. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_schema.h +165 -0
  43. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_select.h +59 -0
  44. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_stream.h +79 -0
  45. data/ext/lwtarantool/vendor/tarantool-c/include/tarantool/tnt_update.h +226 -0
  46. data/ext/lwtarantool/vendor/tarantool-c/include/tp.h +1998 -0
  47. data/ext/lwtarantool/vendor/tarantool-c/test/CMakeLists.txt +36 -0
  48. data/ext/lwtarantool/vendor/tarantool-c/test/common.c +233 -0
  49. data/ext/lwtarantool/vendor/tarantool-c/test/common.h +28 -0
  50. data/ext/lwtarantool/vendor/tarantool-c/test/plain_test.c +152 -0
  51. data/ext/lwtarantool/vendor/tarantool-c/test/tarantool_call.c +57 -0
  52. data/ext/lwtarantool/vendor/tarantool-c/test/tarantool_disconnect.c +31 -0
  53. data/ext/lwtarantool/vendor/tarantool-c/test/tarantool_tcp.c +840 -0
  54. data/ext/lwtarantool/vendor/tarantool-c/test/tarantool_unix.c +384 -0
  55. data/ext/lwtarantool/vendor/tarantool-c/test/test.c +72 -0
  56. data/ext/lwtarantool/vendor/tarantool-c/test/test.h +94 -0
  57. data/ext/lwtarantool/vendor/tarantool-c/test/tnt_assoc.c +6 -0
  58. data/ext/lwtarantool/vendor/tarantool-c/test/tnt_assoc.h +67 -0
  59. data/ext/lwtarantool/vendor/tarantool-c/third_party/PMurHash.c +317 -0
  60. data/ext/lwtarantool/vendor/tarantool-c/third_party/PMurHash.h +68 -0
  61. data/ext/lwtarantool/vendor/tarantool-c/third_party/base64.c +300 -0
  62. data/ext/lwtarantool/vendor/tarantool-c/third_party/base64.h +91 -0
  63. data/ext/lwtarantool/vendor/tarantool-c/third_party/mhash.h +589 -0
  64. data/ext/lwtarantool/vendor/tarantool-c/third_party/sha1.c +219 -0
  65. data/ext/lwtarantool/vendor/tarantool-c/third_party/sha1.h +24 -0
  66. data/ext/lwtarantool/vendor/tarantool-c/third_party/uri.c +6528 -0
  67. data/ext/lwtarantool/vendor/tarantool-c/third_party/uri.h +81 -0
  68. data/ext/lwtarantool/vendor/tarantool-c/tnt/CMakeLists.txt +83 -0
  69. data/ext/lwtarantool/vendor/tarantool-c/tnt/pmatomic.h +494 -0
  70. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_assoc.c +9 -0
  71. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_assoc.h +172 -0
  72. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_auth.c +118 -0
  73. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_buf.c +171 -0
  74. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_call.c +79 -0
  75. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_delete.c +52 -0
  76. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_execute.c +60 -0
  77. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_insert.c +60 -0
  78. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_io.c +520 -0
  79. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_iob.c +75 -0
  80. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_iter.c +293 -0
  81. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_mem.c +82 -0
  82. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_net.c +336 -0
  83. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_object.c +476 -0
  84. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_opt.c +117 -0
  85. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_ping.c +38 -0
  86. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_proto_internal.h +43 -0
  87. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_reply.c +300 -0
  88. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_request.c +336 -0
  89. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_schema.c +334 -0
  90. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_select.c +58 -0
  91. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_stream.c +71 -0
  92. data/ext/lwtarantool/vendor/tarantool-c/tnt/tnt_update.c +247 -0
  93. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/CMakeLists.txt +69 -0
  94. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_dir.c +173 -0
  95. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_dir.h +58 -0
  96. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_log.c +329 -0
  97. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_log.h +119 -0
  98. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_rpl.c +189 -0
  99. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_rpl.h +47 -0
  100. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_snapshot.c +163 -0
  101. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_snapshot.h +50 -0
  102. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_xlog.c +163 -0
  103. data/ext/lwtarantool/vendor/tarantool-c/tntrpl/tnt_xlog.h +50 -0
  104. data/lib/lwtarantool/connection.rb +84 -0
  105. data/lib/lwtarantool/request.rb +58 -0
  106. data/lib/lwtarantool.rb +23 -0
  107. metadata +164 -0
@@ -0,0 +1,2195 @@
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
+ MP_LOAD_STORE(u8, uint8_t, mp_identity);
236
+
237
+ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
238
+
239
+ MP_LOAD_STORE(u16, uint16_t, mp_bswap_u16);
240
+ MP_LOAD_STORE(u32, uint32_t, mp_bswap_u32);
241
+ 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
+ mp_load_float(const char **data)
287
+ {
288
+ union mp_float_cast cast = *(union mp_float_cast *) *data;
289
+ *data += sizeof(cast);
290
+ cast.u32 = mp_bswap_u32(cast.u32);
291
+ return cast.f;
292
+ }
293
+
294
+ MP_IMPL double
295
+ mp_load_double(const char **data)
296
+ {
297
+ union mp_double_cast cast = *(union mp_double_cast *) *data;
298
+ *data += sizeof(cast);
299
+ cast.u64 = mp_bswap_u64(cast.u64);
300
+ return cast.d;
301
+ }
302
+
303
+ MP_IMPL char *
304
+ mp_store_float(char *data, float val)
305
+ {
306
+ union mp_float_cast cast;
307
+ cast.f = val;
308
+ cast.u32 = mp_bswap_u32(cast.u32);
309
+ *(union mp_float_cast *) (data) = cast;
310
+ return data + sizeof(cast);
311
+ }
312
+
313
+ MP_IMPL char *
314
+ mp_store_double(char *data, double val)
315
+ {
316
+ union mp_double_cast cast;
317
+ cast.d = val;
318
+ cast.u64 = mp_bswap_u64(cast.u64);
319
+ *(union mp_double_cast *) (data) = cast;
320
+ 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
+ mp_typeof(const char c)
1194
+ {
1195
+ return mp_type_hint[(uint8_t) c];
1196
+ }
1197
+
1198
+ MP_IMPL uint32_t
1199
+ mp_sizeof_array(uint32_t size)
1200
+ {
1201
+ if (size <= 15) {
1202
+ return 1;
1203
+ } else if (size <= UINT16_MAX) {
1204
+ return 1 + sizeof(uint16_t);
1205
+ } else {
1206
+ return 1 + sizeof(uint32_t);
1207
+ }
1208
+ }
1209
+
1210
+ MP_IMPL char *
1211
+ mp_encode_array(char *data, uint32_t size)
1212
+ {
1213
+ if (size <= 15) {
1214
+ return mp_store_u8(data, 0x90 | size);
1215
+ } else if (size <= UINT16_MAX) {
1216
+ data = mp_store_u8(data, 0xdc);
1217
+ data = mp_store_u16(data, size);
1218
+ return data;
1219
+ } else {
1220
+ data = mp_store_u8(data, 0xdd);
1221
+ return mp_store_u32(data, size);
1222
+ }
1223
+ }
1224
+
1225
+ MP_IMPL ptrdiff_t
1226
+ mp_check_array(const char *cur, const char *end)
1227
+ {
1228
+ assert(cur < end);
1229
+ assert(mp_typeof(*cur) == MP_ARRAY);
1230
+ uint8_t c = mp_load_u8(&cur);
1231
+ if (mp_likely(!(c & 0x40)))
1232
+ return cur - end;
1233
+
1234
+ assert(c >= 0xdc && c <= 0xdd); /* must be checked above by mp_typeof */
1235
+ uint32_t hsize = 2U << (c & 0x1); /* 0xdc->2, 0xdd->4 */
1236
+ return hsize - (end - cur);
1237
+ }
1238
+
1239
+ MP_PROTO uint32_t
1240
+ mp_decode_array_slowpath(uint8_t c, const char **data);
1241
+
1242
+ MP_IMPL uint32_t
1243
+ mp_decode_array_slowpath(uint8_t c, const char **data)
1244
+ {
1245
+ uint32_t size;
1246
+ switch (c & 0x1) {
1247
+ case 0xdc & 0x1:
1248
+ size = mp_load_u16(data);
1249
+ return size;
1250
+ case 0xdd & 0x1:
1251
+ size = mp_load_u32(data);
1252
+ return size;
1253
+ default:
1254
+ mp_unreachable();
1255
+ }
1256
+ }
1257
+
1258
+ MP_IMPL MP_ALWAYSINLINE uint32_t
1259
+ mp_decode_array(const char **data)
1260
+ {
1261
+ uint8_t c = mp_load_u8(data);
1262
+
1263
+ if (mp_likely(!(c & 0x40)))
1264
+ return (c & 0xf);
1265
+
1266
+ return mp_decode_array_slowpath(c, data);
1267
+ }
1268
+
1269
+ MP_IMPL uint32_t
1270
+ mp_sizeof_map(uint32_t size)
1271
+ {
1272
+ if (size <= 15) {
1273
+ return 1;
1274
+ } else if (size <= UINT16_MAX) {
1275
+ return 1 + sizeof(uint16_t);
1276
+ } else {
1277
+ return 1 + sizeof(uint32_t);
1278
+ }
1279
+ }
1280
+
1281
+ MP_IMPL char *
1282
+ mp_encode_map(char *data, uint32_t size)
1283
+ {
1284
+ if (size <= 15) {
1285
+ return mp_store_u8(data, 0x80 | size);
1286
+ } else if (size <= UINT16_MAX) {
1287
+ data = mp_store_u8(data, 0xde);
1288
+ data = mp_store_u16(data, size);
1289
+ return data;
1290
+ } else {
1291
+ data = mp_store_u8(data, 0xdf);
1292
+ data = mp_store_u32(data, size);
1293
+ return data;
1294
+ }
1295
+ }
1296
+
1297
+ MP_IMPL ptrdiff_t
1298
+ mp_check_map(const char *cur, const char *end)
1299
+ {
1300
+ assert(cur < end);
1301
+ assert(mp_typeof(*cur) == MP_MAP);
1302
+ uint8_t c = mp_load_u8(&cur);
1303
+ if (mp_likely((c & ~0xfU) == 0x80))
1304
+ return cur - end;
1305
+
1306
+ assert(c >= 0xde && c <= 0xdf); /* must be checked above by mp_typeof */
1307
+ uint32_t hsize = 2U << (c & 0x1); /* 0xde->2, 0xdf->4 */
1308
+ return hsize - (end - cur);
1309
+ }
1310
+
1311
+ MP_IMPL uint32_t
1312
+ mp_decode_map(const char **data)
1313
+ {
1314
+ uint8_t c = mp_load_u8(data);
1315
+ switch (c) {
1316
+ case 0xde:
1317
+ return mp_load_u16(data);
1318
+ case 0xdf:
1319
+ return mp_load_u32(data);
1320
+ default:
1321
+ if (mp_unlikely(c < 0x80 || c > 0x8f))
1322
+ mp_unreachable();
1323
+ return c & 0xf;
1324
+ }
1325
+ }
1326
+
1327
+ MP_IMPL uint32_t
1328
+ mp_sizeof_uint(uint64_t num)
1329
+ {
1330
+ if (num <= 0x7f) {
1331
+ return 1;
1332
+ } else if (num <= UINT8_MAX) {
1333
+ return 1 + sizeof(uint8_t);
1334
+ } else if (num <= UINT16_MAX) {
1335
+ return 1 + sizeof(uint16_t);
1336
+ } else if (num <= UINT32_MAX) {
1337
+ return 1 + sizeof(uint32_t);
1338
+ } else {
1339
+ return 1 + sizeof(uint64_t);
1340
+ }
1341
+ }
1342
+
1343
+ MP_IMPL uint32_t
1344
+ mp_sizeof_int(int64_t num)
1345
+ {
1346
+ assert(num < 0);
1347
+ if (num >= -0x20) {
1348
+ return 1;
1349
+ } else if (num >= INT8_MIN && num <= INT8_MAX) {
1350
+ return 1 + sizeof(int8_t);
1351
+ } else if (num >= INT16_MIN && num <= UINT16_MAX) {
1352
+ return 1 + sizeof(int16_t);
1353
+ } else if (num >= INT32_MIN && num <= UINT32_MAX) {
1354
+ return 1 + sizeof(int32_t);
1355
+ } else {
1356
+ return 1 + sizeof(int64_t);
1357
+ }
1358
+ }
1359
+
1360
+ MP_IMPL ptrdiff_t
1361
+ mp_check_uint(const char *cur, const char *end)
1362
+ {
1363
+ assert(cur < end);
1364
+ assert(mp_typeof(*cur) == MP_UINT);
1365
+ uint8_t c = mp_load_u8(&cur);
1366
+ return mp_parser_hint[c] - (end - cur);
1367
+ }
1368
+
1369
+ MP_IMPL ptrdiff_t
1370
+ mp_check_int(const char *cur, const char *end)
1371
+ {
1372
+ assert(cur < end);
1373
+ assert(mp_typeof(*cur) == MP_INT);
1374
+ uint8_t c = mp_load_u8(&cur);
1375
+ return mp_parser_hint[c] - (end - cur);
1376
+ }
1377
+
1378
+ MP_IMPL char *
1379
+ mp_encode_uint(char *data, uint64_t num)
1380
+ {
1381
+ if (num <= 0x7f) {
1382
+ return mp_store_u8(data, num);
1383
+ } else if (num <= UINT8_MAX) {
1384
+ data = mp_store_u8(data, 0xcc);
1385
+ return mp_store_u8(data, num);
1386
+ } else if (num <= UINT16_MAX) {
1387
+ data = mp_store_u8(data, 0xcd);
1388
+ return mp_store_u16(data, num);
1389
+ } else if (num <= UINT32_MAX) {
1390
+ data = mp_store_u8(data, 0xce);
1391
+ return mp_store_u32(data, num);
1392
+ } else {
1393
+ data = mp_store_u8(data, 0xcf);
1394
+ return mp_store_u64(data, num);
1395
+ }
1396
+ }
1397
+
1398
+ MP_IMPL char *
1399
+ mp_encode_int(char *data, int64_t num)
1400
+ {
1401
+ assert(num < 0);
1402
+ if (num >= -0x20) {
1403
+ return mp_store_u8(data, 0xe0 | num);
1404
+ } else if (num >= INT8_MIN) {
1405
+ data = mp_store_u8(data, 0xd0);
1406
+ return mp_store_u8(data, num);
1407
+ } else if (num >= INT16_MIN) {
1408
+ data = mp_store_u8(data, 0xd1);
1409
+ return mp_store_u16(data, num);
1410
+ } else if (num >= INT32_MIN) {
1411
+ data = mp_store_u8(data, 0xd2);
1412
+ return mp_store_u32(data, num);
1413
+ } else {
1414
+ data = mp_store_u8(data, 0xd3);
1415
+ return mp_store_u64(data, num);
1416
+ }
1417
+ }
1418
+
1419
+ MP_IMPL uint64_t
1420
+ mp_decode_uint(const char **data)
1421
+ {
1422
+ uint8_t c = mp_load_u8(data);
1423
+ switch (c) {
1424
+ case 0xcc:
1425
+ return mp_load_u8(data);
1426
+ case 0xcd:
1427
+ return mp_load_u16(data);
1428
+ case 0xce:
1429
+ return mp_load_u32(data);
1430
+ case 0xcf:
1431
+ return mp_load_u64(data);
1432
+ default:
1433
+ if (mp_unlikely(c > 0x7f))
1434
+ mp_unreachable();
1435
+ return c;
1436
+ }
1437
+ }
1438
+
1439
+ MP_IMPL int
1440
+ mp_compare_uint(const char *data_a, const char *data_b)
1441
+ {
1442
+ uint8_t ca = mp_load_u8(&data_a);
1443
+ uint8_t cb = mp_load_u8(&data_b);
1444
+
1445
+ int r = ca - cb;
1446
+ if (r != 0)
1447
+ return r;
1448
+
1449
+ if (ca <= 0x7f)
1450
+ return 0;
1451
+
1452
+ uint64_t a, b;
1453
+ switch (ca & 0x3) {
1454
+ case 0xcc & 0x3:
1455
+ a = mp_load_u8(&data_a);
1456
+ b = mp_load_u8(&data_b);
1457
+ break;
1458
+ case 0xcd & 0x3:
1459
+ a = mp_load_u16(&data_a);
1460
+ b = mp_load_u16(&data_b);
1461
+ break;
1462
+ case 0xce & 0x3:
1463
+ a = mp_load_u32(&data_a);
1464
+ b = mp_load_u32(&data_b);
1465
+ break;
1466
+ case 0xcf & 0x3:
1467
+ a = mp_load_u64(&data_a);
1468
+ b = mp_load_u64(&data_b);
1469
+ return a < b ? -1 : a > b;
1470
+ break;
1471
+ default:
1472
+ mp_unreachable();
1473
+ }
1474
+
1475
+ int64_t v = (a - b);
1476
+ return (v > 0) - (v < 0);
1477
+ }
1478
+
1479
+ MP_IMPL int64_t
1480
+ mp_decode_int(const char **data)
1481
+ {
1482
+ uint8_t c = mp_load_u8(data);
1483
+ switch (c) {
1484
+ case 0xd0:
1485
+ return (int8_t) mp_load_u8(data);
1486
+ case 0xd1:
1487
+ return (int16_t) mp_load_u16(data);
1488
+ case 0xd2:
1489
+ return (int32_t) mp_load_u32(data);
1490
+ case 0xd3:
1491
+ return (int64_t) mp_load_u64(data);
1492
+ default:
1493
+ if (mp_unlikely(c < 0xe0))
1494
+ mp_unreachable();
1495
+ return (int8_t) (c);
1496
+ }
1497
+ }
1498
+
1499
+ MP_IMPL uint32_t
1500
+ mp_sizeof_float(float num)
1501
+ {
1502
+ (void) num;
1503
+ return 1 + sizeof(float);
1504
+ }
1505
+
1506
+ MP_IMPL uint32_t
1507
+ mp_sizeof_double(double num)
1508
+ {
1509
+ (void) num;
1510
+ return 1 + sizeof(double);
1511
+ }
1512
+
1513
+ MP_IMPL ptrdiff_t
1514
+ mp_check_float(const char *cur, const char *end)
1515
+ {
1516
+ assert(cur < end);
1517
+ assert(mp_typeof(*cur) == MP_FLOAT);
1518
+ return 1 + sizeof(float) - (end - cur);
1519
+ }
1520
+
1521
+ MP_IMPL ptrdiff_t
1522
+ mp_check_double(const char *cur, const char *end)
1523
+ {
1524
+ assert(cur < end);
1525
+ assert(mp_typeof(*cur) == MP_DOUBLE);
1526
+ return 1 + sizeof(double) - (end - cur);
1527
+ }
1528
+
1529
+ MP_IMPL char *
1530
+ mp_encode_float(char *data, float num)
1531
+ {
1532
+ data = mp_store_u8(data, 0xca);
1533
+ return mp_store_float(data, num);
1534
+ }
1535
+
1536
+ MP_IMPL char *
1537
+ mp_encode_double(char *data, double num)
1538
+ {
1539
+ data = mp_store_u8(data, 0xcb);
1540
+ return mp_store_double(data, num);
1541
+ }
1542
+
1543
+ MP_IMPL float
1544
+ mp_decode_float(const char **data)
1545
+ {
1546
+ uint8_t c = mp_load_u8(data);
1547
+ assert(c == 0xca);
1548
+ (void) c;
1549
+ return mp_load_float(data);
1550
+ }
1551
+
1552
+ MP_IMPL double
1553
+ mp_decode_double(const char **data)
1554
+ {
1555
+ uint8_t c = mp_load_u8(data);
1556
+ assert(c == 0xcb);
1557
+ (void) c;
1558
+ return mp_load_double(data);
1559
+ }
1560
+
1561
+ MP_IMPL uint32_t
1562
+ mp_sizeof_strl(uint32_t len)
1563
+ {
1564
+ if (len <= 31) {
1565
+ return 1;
1566
+ } else if (len <= UINT8_MAX) {
1567
+ return 1 + sizeof(uint8_t);
1568
+ } else if (len <= UINT16_MAX) {
1569
+ return 1 + sizeof(uint16_t);
1570
+ } else {
1571
+ return 1 + sizeof(uint32_t);
1572
+ }
1573
+ }
1574
+
1575
+ MP_IMPL uint32_t
1576
+ mp_sizeof_str(uint32_t len)
1577
+ {
1578
+ return mp_sizeof_strl(len) + len;
1579
+ }
1580
+
1581
+ MP_IMPL uint32_t
1582
+ mp_sizeof_binl(uint32_t len)
1583
+ {
1584
+ if (len <= UINT8_MAX) {
1585
+ return 1 + sizeof(uint8_t);
1586
+ } else if (len <= UINT16_MAX) {
1587
+ return 1 + sizeof(uint16_t);
1588
+ } else {
1589
+ return 1 + sizeof(uint32_t);
1590
+ }
1591
+ }
1592
+
1593
+ MP_IMPL uint32_t
1594
+ mp_sizeof_bin(uint32_t len)
1595
+ {
1596
+ return mp_sizeof_binl(len) + len;
1597
+ }
1598
+
1599
+ MP_IMPL char *
1600
+ mp_encode_strl(char *data, uint32_t len)
1601
+ {
1602
+ if (len <= 31) {
1603
+ return mp_store_u8(data, 0xa0 | (uint8_t) len);
1604
+ } else if (len <= UINT8_MAX) {
1605
+ data = mp_store_u8(data, 0xd9);
1606
+ return mp_store_u8(data, len);
1607
+ } else if (len <= UINT16_MAX) {
1608
+ data = mp_store_u8(data, 0xda);
1609
+ return mp_store_u16(data, len);
1610
+ } else {
1611
+ data = mp_store_u8(data, 0xdb);
1612
+ return mp_store_u32(data, len);
1613
+ }
1614
+ }
1615
+
1616
+ MP_IMPL char *
1617
+ mp_encode_str(char *data, const char *str, uint32_t len)
1618
+ {
1619
+ data = mp_encode_strl(data, len);
1620
+ memcpy(data, str, len);
1621
+ return data + len;
1622
+ }
1623
+
1624
+ MP_IMPL char *
1625
+ mp_encode_binl(char *data, uint32_t len)
1626
+ {
1627
+ if (len <= UINT8_MAX) {
1628
+ data = mp_store_u8(data, 0xc4);
1629
+ return mp_store_u8(data, len);
1630
+ } else if (len <= UINT16_MAX) {
1631
+ data = mp_store_u8(data, 0xc5);
1632
+ return mp_store_u16(data, len);
1633
+ } else {
1634
+ data = mp_store_u8(data, 0xc6);
1635
+ return mp_store_u32(data, len);
1636
+ }
1637
+ }
1638
+
1639
+ MP_IMPL char *
1640
+ mp_encode_bin(char *data, const char *str, uint32_t len)
1641
+ {
1642
+ data = mp_encode_binl(data, len);
1643
+ memcpy(data, str, len);
1644
+ return data + len;
1645
+ }
1646
+
1647
+ MP_IMPL ptrdiff_t
1648
+ mp_check_strl(const char *cur, const char *end)
1649
+ {
1650
+ assert(cur < end);
1651
+ assert(mp_typeof(*cur) == MP_STR);
1652
+
1653
+ uint8_t c = mp_load_u8(&cur);
1654
+ if (mp_likely(c & ~0x1f) == 0xa0)
1655
+ return cur - end;
1656
+
1657
+ assert(c >= 0xd9 && c <= 0xdb); /* must be checked above by mp_typeof */
1658
+ uint32_t hsize = 1U << (c & 0x3) >> 1; /* 0xd9->1, 0xda->2, 0xdb->4 */
1659
+ return hsize - (end - cur);
1660
+ }
1661
+
1662
+ MP_IMPL ptrdiff_t
1663
+ mp_check_binl(const char *cur, const char *end)
1664
+ {
1665
+ uint8_t c = mp_load_u8(&cur);
1666
+ assert(cur < end);
1667
+ assert(mp_typeof(c) == MP_BIN);
1668
+
1669
+ assert(c >= 0xc4 && c <= 0xc6); /* must be checked above by mp_typeof */
1670
+ uint32_t hsize = 1U << (c & 0x3); /* 0xc4->1, 0xc5->2, 0xc6->4 */
1671
+ return hsize - (end - cur);
1672
+ }
1673
+
1674
+ MP_IMPL uint32_t
1675
+ mp_decode_strl(const char **data)
1676
+ {
1677
+ uint8_t c = mp_load_u8(data);
1678
+ switch (c) {
1679
+ case 0xd9:
1680
+ return mp_load_u8(data);
1681
+ case 0xda:
1682
+ return mp_load_u16(data);
1683
+ case 0xdb:
1684
+ return mp_load_u32(data);
1685
+ default:
1686
+ if (mp_unlikely(c < 0xa0 || c > 0xbf))
1687
+ mp_unreachable();
1688
+ return c & 0x1f;
1689
+ }
1690
+ }
1691
+
1692
+ MP_IMPL const char *
1693
+ mp_decode_str(const char **data, uint32_t *len)
1694
+ {
1695
+ assert(len != NULL);
1696
+
1697
+ *len = mp_decode_strl(data);
1698
+ const char *str = *data;
1699
+ *data += *len;
1700
+ return str;
1701
+ }
1702
+
1703
+ MP_IMPL uint32_t
1704
+ mp_decode_binl(const char **data)
1705
+ {
1706
+ uint8_t c = mp_load_u8(data);
1707
+
1708
+ switch (c) {
1709
+ case 0xc4:
1710
+ return mp_load_u8(data);
1711
+ case 0xc5:
1712
+ return mp_load_u16(data);
1713
+ case 0xc6:
1714
+ return mp_load_u32(data);
1715
+ default:
1716
+ mp_unreachable();
1717
+ }
1718
+ }
1719
+
1720
+ MP_IMPL const char *
1721
+ mp_decode_bin(const char **data, uint32_t *len)
1722
+ {
1723
+ assert(len != NULL);
1724
+
1725
+ *len = mp_decode_binl(data);
1726
+ const char *str = *data;
1727
+ *data += *len;
1728
+ return str;
1729
+ }
1730
+
1731
+ MP_IMPL uint32_t
1732
+ mp_decode_strbinl(const char **data)
1733
+ {
1734
+ uint8_t c = mp_load_u8(data);
1735
+
1736
+ switch (c) {
1737
+ case 0xd9:
1738
+ return mp_load_u8(data);
1739
+ case 0xda:
1740
+ return mp_load_u16(data);
1741
+ case 0xdb:
1742
+ return mp_load_u32(data);
1743
+ case 0xc4:
1744
+ return mp_load_u8(data);
1745
+ case 0xc5:
1746
+ return mp_load_u16(data);
1747
+ case 0xc6:
1748
+ return mp_load_u32(data);
1749
+ default:
1750
+ if (mp_unlikely(c < 0xa0 || c > 0xbf))
1751
+ mp_unreachable();
1752
+ return c & 0x1f;
1753
+ }
1754
+ }
1755
+
1756
+ MP_IMPL const char *
1757
+ mp_decode_strbin(const char **data, uint32_t *len)
1758
+ {
1759
+ assert(len != NULL);
1760
+
1761
+ *len = mp_decode_strbinl(data);
1762
+ const char *str = *data;
1763
+ *data += *len;
1764
+ return str;
1765
+ }
1766
+
1767
+ MP_IMPL uint32_t
1768
+ mp_sizeof_nil()
1769
+ {
1770
+ return 1;
1771
+ }
1772
+
1773
+ MP_IMPL char *
1774
+ mp_encode_nil(char *data)
1775
+ {
1776
+ return mp_store_u8(data, 0xc0);
1777
+ }
1778
+
1779
+ MP_IMPL ptrdiff_t
1780
+ mp_check_nil(const char *cur, const char *end)
1781
+ {
1782
+ assert(cur < end);
1783
+ assert(mp_typeof(*cur) == MP_NIL);
1784
+ return 1 - (end - cur);
1785
+ }
1786
+
1787
+ MP_IMPL void
1788
+ mp_decode_nil(const char **data)
1789
+ {
1790
+ uint8_t c = mp_load_u8(data);
1791
+ assert(c == 0xc0);
1792
+ (void) c;
1793
+ }
1794
+
1795
+ MP_IMPL uint32_t
1796
+ mp_sizeof_bool(bool val)
1797
+ {
1798
+ (void) val;
1799
+ return 1;
1800
+ }
1801
+
1802
+ MP_IMPL char *
1803
+ mp_encode_bool(char *data, bool val)
1804
+ {
1805
+ return mp_store_u8(data, 0xc2 | (val & 1));
1806
+ }
1807
+
1808
+ MP_IMPL ptrdiff_t
1809
+ mp_check_bool(const char *cur, const char *end)
1810
+ {
1811
+ assert(cur < end);
1812
+ assert(mp_typeof(*cur) == MP_BOOL);
1813
+ return 1 - (end - cur);
1814
+ }
1815
+
1816
+ MP_IMPL bool
1817
+ mp_decode_bool(const char **data)
1818
+ {
1819
+ uint8_t c = mp_load_u8(data);
1820
+ switch (c) {
1821
+ case 0xc3:
1822
+ return true;
1823
+ case 0xc2:
1824
+ return false;
1825
+ default:
1826
+ mp_unreachable();
1827
+ }
1828
+ }
1829
+
1830
+ MP_IMPL int
1831
+ mp_read_int32(const char **data, int32_t *ret)
1832
+ {
1833
+ uint32_t uval;
1834
+ const char *p = *data;
1835
+ uint8_t c = mp_load_u8(&p);
1836
+ switch (c) {
1837
+ case 0xd0:
1838
+ *ret = (int8_t) mp_load_u8(&p);
1839
+ break;
1840
+ case 0xd1:
1841
+ *ret = (int16_t) mp_load_u16(&p);
1842
+ break;
1843
+ case 0xd2:
1844
+ *ret = (int32_t) mp_load_u32(&p);
1845
+ break;
1846
+ case 0xcc:
1847
+ *ret = mp_load_u8(&p);
1848
+ break;
1849
+ case 0xcd:
1850
+ *ret = mp_load_u16(&p);
1851
+ break;
1852
+ case 0xce:
1853
+ uval = mp_load_u32(&p);
1854
+ if (mp_unlikely(uval > INT32_MAX))
1855
+ return -1;
1856
+ *ret = uval;
1857
+ break;
1858
+ default:
1859
+ if (mp_unlikely(c < 0xe0 && c > 0x7f))
1860
+ return -1;
1861
+ *ret = (int8_t) c;
1862
+ break;
1863
+ }
1864
+ *data = p;
1865
+ return 0;
1866
+ }
1867
+
1868
+ MP_IMPL int
1869
+ mp_read_int64(const char **data, int64_t *ret)
1870
+ {
1871
+ uint64_t uval;
1872
+ const char *p = *data;
1873
+ uint8_t c = mp_load_u8(&p);
1874
+ switch (c) {
1875
+ case 0xd0:
1876
+ *ret = (int8_t) mp_load_u8(&p);
1877
+ break;
1878
+ case 0xd1:
1879
+ *ret = (int16_t) mp_load_u16(&p);
1880
+ break;
1881
+ case 0xd2:
1882
+ *ret = (int32_t) mp_load_u32(&p);
1883
+ break;
1884
+ case 0xd3:
1885
+ *ret = (int64_t) mp_load_u64(&p);
1886
+ break;
1887
+ case 0xcc:
1888
+ *ret = mp_load_u8(&p);
1889
+ break;
1890
+ case 0xcd:
1891
+ *ret = mp_load_u16(&p);
1892
+ break;
1893
+ case 0xce:
1894
+ *ret = mp_load_u32(&p);
1895
+ break;
1896
+ case 0xcf:
1897
+ uval = mp_load_u64(&p);
1898
+ if (uval > INT64_MAX)
1899
+ return -1;
1900
+ *ret = uval;
1901
+ break;
1902
+ default:
1903
+ if (mp_unlikely(c < 0xe0 && c > 0x7f))
1904
+ return -1;
1905
+ *ret = (int8_t) c;
1906
+ break;
1907
+ }
1908
+ *data = p;
1909
+ return 0;
1910
+ }
1911
+
1912
+ MP_IMPL int
1913
+ mp_read_double(const char **data, double *ret)
1914
+ {
1915
+ int64_t ival;
1916
+ uint64_t uval;
1917
+ double val;
1918
+ const char *p = *data;
1919
+ uint8_t c = mp_load_u8(&p);
1920
+ switch (c) {
1921
+ case 0xd0:
1922
+ *ret = (int8_t) mp_load_u8(&p);
1923
+ break;
1924
+ case 0xd1:
1925
+ *ret = (int16_t) mp_load_u16(&p);
1926
+ break;
1927
+ case 0xd2:
1928
+ *ret = (int32_t) mp_load_u32(&p);
1929
+ break;
1930
+ case 0xd3:
1931
+ val = ival = (int64_t) mp_load_u64(&p);
1932
+ if ((int64_t)val != ival)
1933
+ return -1;
1934
+ *ret = val;
1935
+ break;
1936
+ case 0xcc:
1937
+ *ret = mp_load_u8(&p);
1938
+ break;
1939
+ case 0xcd:
1940
+ *ret = mp_load_u16(&p);
1941
+ break;
1942
+ case 0xce:
1943
+ *ret = mp_load_u32(&p);
1944
+ break;
1945
+ case 0xcf:
1946
+ val = uval = mp_load_u64(&p);
1947
+ if ((uint64_t)val != uval)
1948
+ return -1;
1949
+ *ret = val;
1950
+ break;
1951
+ case 0xca:
1952
+ *ret = mp_load_float(&p);
1953
+ break;
1954
+ case 0xcb:
1955
+ *ret = mp_load_double(&p);
1956
+ break;
1957
+ default:
1958
+ if (mp_unlikely(c < 0xe0 && c > 0x7f))
1959
+ return -1;
1960
+ *ret = (int8_t) c;
1961
+ break;
1962
+ }
1963
+ *data = p;
1964
+ return 0;
1965
+ }
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
+ mp_next_slowpath(const char **data, int64_t k)
1987
+ {
1988
+ for (; k > 0; k--) {
1989
+ uint8_t c = mp_load_u8(data);
1990
+ int l = mp_parser_hint[c];
1991
+ if (mp_likely(l >= 0)) {
1992
+ *data += l;
1993
+ continue;
1994
+ } else if (mp_likely(l > MP_HINT)) {
1995
+ k -= l;
1996
+ continue;
1997
+ }
1998
+
1999
+ uint32_t len;
2000
+ switch (l) {
2001
+ case MP_HINT_STR_8:
2002
+ /* MP_STR (8) */
2003
+ len = mp_load_u8(data);
2004
+ *data += len;
2005
+ break;
2006
+ case MP_HINT_STR_16:
2007
+ /* MP_STR (16) */
2008
+ len = mp_load_u16(data);
2009
+ *data += len;
2010
+ break;
2011
+ case MP_HINT_STR_32:
2012
+ /* MP_STR (32) */
2013
+ len = mp_load_u32(data);
2014
+ *data += len;
2015
+ break;
2016
+ case MP_HINT_ARRAY_16:
2017
+ /* MP_ARRAY (16) */
2018
+ k += mp_load_u16(data);
2019
+ break;
2020
+ case MP_HINT_ARRAY_32:
2021
+ /* MP_ARRAY (32) */
2022
+ k += mp_load_u32(data);
2023
+ break;
2024
+ case MP_HINT_MAP_16:
2025
+ /* MP_MAP (16) */
2026
+ k += 2 * mp_load_u16(data);
2027
+ break;
2028
+ case MP_HINT_MAP_32:
2029
+ /* MP_MAP (32) */
2030
+ k += 2 * mp_load_u32(data);
2031
+ break;
2032
+ case MP_HINT_EXT_8:
2033
+ /* MP_EXT (8) */
2034
+ len = mp_load_u8(data);
2035
+ mp_load_u8(data);
2036
+ *data += len;
2037
+ break;
2038
+ case MP_HINT_EXT_16:
2039
+ /* MP_EXT (16) */
2040
+ len = mp_load_u16(data);
2041
+ mp_load_u8(data);
2042
+ *data += len;
2043
+ break;
2044
+ case MP_HINT_EXT_32:
2045
+ /* MP_EXT (32) */
2046
+ len = mp_load_u32(data);
2047
+ mp_load_u8(data);
2048
+ *data += len;
2049
+ break;
2050
+ default:
2051
+ mp_unreachable();
2052
+ }
2053
+ }
2054
+ }
2055
+
2056
+ MP_IMPL void
2057
+ mp_next(const char **data)
2058
+ {
2059
+ int64_t k = 1;
2060
+ for (; k > 0; k--) {
2061
+ uint8_t c = mp_load_u8(data);
2062
+ int l = mp_parser_hint[c];
2063
+ if (mp_likely(l >= 0)) {
2064
+ *data += l;
2065
+ continue;
2066
+ } else if (mp_likely(c == 0xd9)){
2067
+ /* MP_STR (8) */
2068
+ uint8_t len = mp_load_u8(data);
2069
+ *data += len;
2070
+ continue;
2071
+ } else if (l > MP_HINT) {
2072
+ k -= l;
2073
+ continue;
2074
+ } else {
2075
+ *data -= sizeof(uint8_t);
2076
+ return mp_next_slowpath(data, k);
2077
+ }
2078
+ }
2079
+ }
2080
+
2081
+ MP_IMPL int
2082
+ 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
+ for (k = 1; k > 0; k--) {
2090
+ MP_CHECK_LEN(1);
2091
+ uint8_t c = mp_load_u8(data);
2092
+ int l = mp_parser_hint[c];
2093
+ if (mp_likely(l >= 0)) {
2094
+ MP_CHECK_LEN(l);
2095
+ *data += l;
2096
+ continue;
2097
+ } else if (mp_likely(l > MP_HINT)) {
2098
+ k -= l;
2099
+ continue;
2100
+ }
2101
+
2102
+ uint32_t len;
2103
+ switch (l) {
2104
+ case MP_HINT_STR_8:
2105
+ /* MP_STR (8) */
2106
+ MP_CHECK_LEN(sizeof(uint8_t));
2107
+ len = mp_load_u8(data);
2108
+ MP_CHECK_LEN(len);
2109
+ *data += len;
2110
+ break;
2111
+ case MP_HINT_STR_16:
2112
+ /* MP_STR (16) */
2113
+ MP_CHECK_LEN(sizeof(uint16_t));
2114
+ len = mp_load_u16(data);
2115
+ MP_CHECK_LEN(len);
2116
+ *data += len;
2117
+ break;
2118
+ case MP_HINT_STR_32:
2119
+ /* MP_STR (32) */
2120
+ MP_CHECK_LEN(sizeof(uint32_t))
2121
+ len = mp_load_u32(data);
2122
+ MP_CHECK_LEN(len);
2123
+ *data += len;
2124
+ break;
2125
+ case MP_HINT_ARRAY_16:
2126
+ /* MP_ARRAY (16) */
2127
+ MP_CHECK_LEN(sizeof(uint16_t));
2128
+ k += mp_load_u16(data);
2129
+ break;
2130
+ case MP_HINT_ARRAY_32:
2131
+ /* MP_ARRAY (32) */
2132
+ MP_CHECK_LEN(sizeof(uint32_t));
2133
+ k += mp_load_u32(data);
2134
+ break;
2135
+ case MP_HINT_MAP_16:
2136
+ /* MP_MAP (16) */
2137
+ MP_CHECK_LEN(sizeof(uint16_t));
2138
+ k += 2 * mp_load_u16(data);
2139
+ break;
2140
+ case MP_HINT_MAP_32:
2141
+ /* MP_MAP (32) */
2142
+ MP_CHECK_LEN(sizeof(uint32_t));
2143
+ k += 2 * mp_load_u32(data);
2144
+ break;
2145
+ case MP_HINT_EXT_8:
2146
+ /* MP_EXT (8) */
2147
+ MP_CHECK_LEN(sizeof(uint8_t) + sizeof(uint8_t));
2148
+ len = mp_load_u8(data);
2149
+ mp_load_u8(data);
2150
+ MP_CHECK_LEN(len);
2151
+ *data += len;
2152
+ break;
2153
+ case MP_HINT_EXT_16:
2154
+ /* MP_EXT (16) */
2155
+ MP_CHECK_LEN(sizeof(uint16_t) + sizeof(uint8_t));
2156
+ len = mp_load_u16(data);
2157
+ mp_load_u8(data);
2158
+ MP_CHECK_LEN(len);
2159
+ *data += len;
2160
+ break;
2161
+ case MP_HINT_EXT_32:
2162
+ /* MP_EXT (32) */
2163
+ MP_CHECK_LEN(sizeof(uint32_t) + sizeof(uint8_t));
2164
+ len = mp_load_u32(data);
2165
+ mp_load_u8(data);
2166
+ MP_CHECK_LEN(len);
2167
+ *data += len;
2168
+ break;
2169
+ default:
2170
+ mp_unreachable();
2171
+ }
2172
+ }
2173
+
2174
+ assert(*data <= end);
2175
+ #undef MP_CHECK_LEN
2176
+ return 0;
2177
+ }
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 */