4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; only
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #define MSGPACK_FIXSTR_ID_MASK 0xA0
26 #define MSGPACK_FIXMAP_ID_MASK 0x80
27 #define MSGPACK_FIXARRAY_ID_MASK 0x90
29 #define MSGPACK_NIL_ID 0xC0
30 #define MSGPACK_FALSE_ID 0xC2
31 #define MSGPACK_TRUE_ID 0xC3
32 #define MSGPACK_MAP16_ID 0xDE
33 #define MSGPACK_ARRAY16_ID 0xDC
35 #define MSGPACK_UINT8_ID 0xCC
36 #define MSGPACK_UINT16_ID 0xCD
37 #define MSGPACK_UINT32_ID 0xCE
38 #define MSGPACK_UINT64_ID 0xCF
40 #define MSGPACK_INT8_ID 0xD0
41 #define MSGPACK_INT16_ID 0xD1
42 #define MSGPACK_INT32_ID 0xD2
43 #define MSGPACK_INT64_ID 0xD3
45 #define MSGPACK_FLOAT64_ID 0xCB
46 #define MSGPACK_STR16_ID 0xDA
48 #define MSGPACK_FIXINT_MAX ((1 << 7) - 1)
49 #define MSGPACK_FIXINT_MIN -(1 << 5)
50 #define MSGPACK_FIXMAP_MAX_COUNT 15
51 #define MSGPACK_FIXARRAY_MAX_COUNT 15
52 #define MSGPACK_FIXSTR_MAX_LENGTH 31
55 #include <linux/bug.h>
56 #include <linux/string.h>
57 #include <linux/types.h>
59 #include <lttng/msgpack.h>
61 #define INT8_MIN (-128)
62 #define INT16_MIN (-32767-1)
63 #define INT32_MIN (-2147483647-1)
64 #define INT8_MAX (127)
65 #define INT16_MAX (32767)
66 #define INT32_MAX (2147483647)
67 #define UINT8_MAX (255)
68 #define UINT16_MAX (65535)
69 #define UINT32_MAX (4294967295U)
71 #define byteswap_host_to_be16(_tmp) cpu_to_be16(_tmp)
72 #define byteswap_host_to_be32(_tmp) cpu_to_be32(_tmp)
73 #define byteswap_host_to_be64(_tmp) cpu_to_be64(_tmp)
75 #define lttng_msgpack_assert(cond) WARN_ON(!(cond))
77 #else /* __KERNEL__ */
85 #define byteswap_host_to_be16(_tmp) htobe16(_tmp)
86 #define byteswap_host_to_be32(_tmp) htobe32(_tmp)
87 #define byteswap_host_to_be64(_tmp) htobe64(_tmp)
89 #define lttng_msgpack_assert(cond) ({ \
91 fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
93 #endif /* __KERNEL__ */
95 static inline int lttng_msgpack_append_buffer(
96 struct lttng_msgpack_writer
*writer
,
102 lttng_msgpack_assert(buf
);
104 /* Ensure we are not trying to write after the end of the buffer. */
105 if (writer
->write_pos
+ length
> writer
->end_write_pos
) {
110 memcpy(writer
->write_pos
, buf
, length
);
111 writer
->write_pos
+= length
;
116 static inline int lttng_msgpack_append_u8(
117 struct lttng_msgpack_writer
*writer
, uint8_t value
)
119 return lttng_msgpack_append_buffer(writer
, &value
, sizeof(value
));
122 static inline int lttng_msgpack_append_u16(
123 struct lttng_msgpack_writer
*writer
, uint16_t value
)
125 value
= byteswap_host_to_be16(value
);
127 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
130 static inline int lttng_msgpack_append_u32(
131 struct lttng_msgpack_writer
*writer
, uint32_t value
)
133 value
= byteswap_host_to_be32(value
);
135 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
138 static inline int lttng_msgpack_append_u64(
139 struct lttng_msgpack_writer
*writer
, uint64_t value
)
141 value
= byteswap_host_to_be64(value
);
143 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
146 static inline int lttng_msgpack_append_f64(
147 struct lttng_msgpack_writer
*writer
, double value
)
157 return lttng_msgpack_append_u64(writer
, u
.u
);
160 static inline int lttng_msgpack_append_i8(
161 struct lttng_msgpack_writer
*writer
, int8_t value
)
163 return lttng_msgpack_append_u8(writer
, (uint8_t) value
);
166 static inline int lttng_msgpack_append_i16(
167 struct lttng_msgpack_writer
*writer
, int16_t value
)
169 return lttng_msgpack_append_u16(writer
, (uint16_t) value
);
172 static inline int lttng_msgpack_append_i32(
173 struct lttng_msgpack_writer
*writer
, int32_t value
)
175 return lttng_msgpack_append_u32(writer
, (uint32_t) value
);
178 static inline int lttng_msgpack_append_i64(
179 struct lttng_msgpack_writer
*writer
, int64_t value
)
181 return lttng_msgpack_append_u64(writer
, (uint64_t) value
);
184 static inline int lttng_msgpack_encode_f64(
185 struct lttng_msgpack_writer
*writer
, double value
)
189 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FLOAT64_ID
);
193 ret
= lttng_msgpack_append_f64(writer
, value
);
201 static inline int lttng_msgpack_encode_fixmap(
202 struct lttng_msgpack_writer
*writer
, uint8_t count
)
206 lttng_msgpack_assert(count
<= MSGPACK_FIXMAP_MAX_COUNT
);
208 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXMAP_ID_MASK
| count
);
216 static inline int lttng_msgpack_encode_map16(
217 struct lttng_msgpack_writer
*writer
, uint16_t count
)
221 lttng_msgpack_assert(count
> MSGPACK_FIXMAP_MAX_COUNT
);
223 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_MAP16_ID
);
227 ret
= lttng_msgpack_append_u16(writer
, count
);
235 static inline int lttng_msgpack_encode_fixarray(
236 struct lttng_msgpack_writer
*writer
, uint8_t count
)
240 lttng_msgpack_assert(count
<= MSGPACK_FIXARRAY_MAX_COUNT
);
242 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXARRAY_ID_MASK
| count
);
250 static inline int lttng_msgpack_encode_array16(
251 struct lttng_msgpack_writer
*writer
, uint16_t count
)
255 lttng_msgpack_assert(count
> MSGPACK_FIXARRAY_MAX_COUNT
);
257 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_ARRAY16_ID
);
261 ret
= lttng_msgpack_append_u16(writer
, count
);
269 static inline int lttng_msgpack_encode_fixstr(
270 struct lttng_msgpack_writer
*writer
,
276 lttng_msgpack_assert(len
<= MSGPACK_FIXSTR_MAX_LENGTH
);
278 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXSTR_ID_MASK
| len
);
282 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
290 static inline int lttng_msgpack_encode_str16(
291 struct lttng_msgpack_writer
*writer
,
297 lttng_msgpack_assert(len
> MSGPACK_FIXSTR_MAX_LENGTH
);
299 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_STR16_ID
);
303 ret
= lttng_msgpack_append_u16(writer
, len
);
307 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
315 int lttng_msgpack_begin_map(struct lttng_msgpack_writer
*writer
, size_t count
)
319 if (count
< 0 || count
>= (1 << 16)) {
324 if (count
<= MSGPACK_FIXMAP_MAX_COUNT
)
325 ret
= lttng_msgpack_encode_fixmap(writer
, count
);
327 ret
= lttng_msgpack_encode_map16(writer
, count
);
329 writer
->map_nesting
++;
334 int lttng_msgpack_end_map(struct lttng_msgpack_writer
*writer
)
336 lttng_msgpack_assert(writer
->map_nesting
> 0);
337 writer
->map_nesting
--;
341 int lttng_msgpack_begin_array(
342 struct lttng_msgpack_writer
*writer
, size_t count
)
346 if (count
< 0 || count
>= (1 << 16)) {
351 if (count
<= MSGPACK_FIXARRAY_MAX_COUNT
)
352 ret
= lttng_msgpack_encode_fixarray(writer
, count
);
354 ret
= lttng_msgpack_encode_array16(writer
, count
);
356 writer
->array_nesting
++;
361 int lttng_msgpack_end_array(struct lttng_msgpack_writer
*writer
)
363 lttng_msgpack_assert(writer
->array_nesting
> 0);
364 writer
->array_nesting
--;
368 int lttng_msgpack_write_str(struct lttng_msgpack_writer
*writer
,
372 size_t length
= strlen(str
);
373 if (length
< 0 || length
>= (1 << 16)) {
378 if (length
<= MSGPACK_FIXSTR_MAX_LENGTH
)
379 ret
= lttng_msgpack_encode_fixstr(writer
, str
, length
);
381 ret
= lttng_msgpack_encode_str16(writer
, str
, length
);
387 int lttng_msgpack_write_nil(struct lttng_msgpack_writer
*writer
)
389 return lttng_msgpack_append_u8(writer
, MSGPACK_NIL_ID
);
392 int lttng_msgpack_write_true(struct lttng_msgpack_writer
*writer
)
394 return lttng_msgpack_append_u8(writer
, MSGPACK_TRUE_ID
);
397 int lttng_msgpack_write_false(struct lttng_msgpack_writer
*writer
)
399 return lttng_msgpack_append_u8(writer
, MSGPACK_FALSE_ID
);
402 int lttng_msgpack_write_unsigned_integer(
403 struct lttng_msgpack_writer
*writer
, uint64_t value
)
407 if (value
<= MSGPACK_FIXINT_MAX
) {
408 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
411 } else if (value
<= UINT8_MAX
) {
412 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT8_ID
);
416 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
419 } else if (value
<= UINT16_MAX
) {
420 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT16_ID
);
424 ret
= lttng_msgpack_append_u16(writer
, (uint16_t) value
);
427 } else if (value
<= UINT32_MAX
) {
428 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT32_ID
);
432 ret
= lttng_msgpack_append_u32(writer
, (uint32_t) value
);
436 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT64_ID
);
440 ret
= lttng_msgpack_append_u64(writer
, value
);
449 int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer
*writer
, int64_t value
)
453 if (value
>= MSGPACK_FIXINT_MIN
&& value
<= MSGPACK_FIXINT_MAX
){
454 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
457 } else if (value
>= INT8_MIN
&& value
<= INT8_MAX
) {
458 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT8_ID
);
462 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
465 } else if (value
>= INT16_MIN
&& value
<= INT16_MAX
) {
466 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT16_ID
);
470 ret
= lttng_msgpack_append_i16(writer
, (int16_t) value
);
473 } else if (value
>= INT32_MIN
&& value
<= INT32_MAX
) {
474 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT32_ID
);
478 ret
= lttng_msgpack_append_i32(writer
, (int32_t) value
);
482 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT64_ID
);
486 ret
= lttng_msgpack_append_i64(writer
, value
);
495 int lttng_msgpack_write_double(struct lttng_msgpack_writer
*writer
, double value
)
497 return lttng_msgpack_encode_f64(writer
, value
);
500 void lttng_msgpack_writer_init(struct lttng_msgpack_writer
*writer
,
501 uint8_t *buffer
, size_t size
)
503 lttng_msgpack_assert(buffer
);
504 lttng_msgpack_assert(size
>= 0);
506 writer
->buffer
= buffer
;
507 writer
->write_pos
= buffer
;
508 writer
->end_write_pos
= buffer
+ size
;
510 writer
->array_nesting
= 0;
511 writer
->map_nesting
= 0;
514 void lttng_msgpack_writer_fini(struct lttng_msgpack_writer
*writer
)
516 memset(writer
, 0, sizeof(*writer
));