2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
11 #define MSGPACK_FIXSTR_ID_MASK 0xA0
12 #define MSGPACK_FIXMAP_ID_MASK 0x80
13 #define MSGPACK_FIXARRAY_ID_MASK 0x90
15 #define MSGPACK_NIL_ID 0xC0
16 #define MSGPACK_FALSE_ID 0xC2
17 #define MSGPACK_TRUE_ID 0xC3
18 #define MSGPACK_MAP16_ID 0xDE
19 #define MSGPACK_ARRAY16_ID 0xDC
21 #define MSGPACK_UINT8_ID 0xCC
22 #define MSGPACK_UINT16_ID 0xCD
23 #define MSGPACK_UINT32_ID 0xCE
24 #define MSGPACK_UINT64_ID 0xCF
26 #define MSGPACK_INT8_ID 0xD0
27 #define MSGPACK_INT16_ID 0xD1
28 #define MSGPACK_INT32_ID 0xD2
29 #define MSGPACK_INT64_ID 0xD3
31 #define MSGPACK_FLOAT64_ID 0xCB
32 #define MSGPACK_STR16_ID 0xDA
34 #define MSGPACK_FIXINT_MAX ((1 << 7) - 1)
35 #define MSGPACK_FIXINT_MIN -(1 << 5)
36 #define MSGPACK_FIXMAP_MAX_COUNT 15
37 #define MSGPACK_FIXARRAY_MAX_COUNT 15
38 #define MSGPACK_FIXSTR_MAX_LENGTH 31
41 #include <linux/bug.h>
42 #include <linux/string.h>
43 #include <linux/types.h>
45 #include <lttng/msgpack.h>
47 #define INT8_MIN (-128)
48 #define INT16_MIN (-32767-1)
49 #define INT32_MIN (-2147483647-1)
50 #define INT8_MAX (127)
51 #define INT16_MAX (32767)
52 #define INT32_MAX (2147483647)
53 #define UINT8_MAX (255)
54 #define UINT16_MAX (65535)
55 #define UINT32_MAX (4294967295U)
57 #define byteswap_host_to_be16(_tmp) cpu_to_be16(_tmp)
58 #define byteswap_host_to_be32(_tmp) cpu_to_be32(_tmp)
59 #define byteswap_host_to_be64(_tmp) cpu_to_be64(_tmp)
61 #define lttng_msgpack_assert(cond) WARN_ON(!(cond))
63 #else /* __KERNEL__ */
65 #include <lttng/ust-endian.h>
71 #define byteswap_host_to_be16(_tmp) htobe16(_tmp)
72 #define byteswap_host_to_be32(_tmp) htobe32(_tmp)
73 #define byteswap_host_to_be64(_tmp) htobe64(_tmp)
75 #define lttng_msgpack_assert(cond) ({ \
77 fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
79 #endif /* __KERNEL__ */
81 static inline int lttng_msgpack_append_buffer(
82 struct lttng_msgpack_writer
*writer
,
88 lttng_msgpack_assert(buf
);
90 /* Ensure we are not trying to write after the end of the buffer. */
91 if (writer
->write_pos
+ length
> writer
->end_write_pos
) {
96 memcpy(writer
->write_pos
, buf
, length
);
97 writer
->write_pos
+= length
;
102 static inline int lttng_msgpack_append_u8(
103 struct lttng_msgpack_writer
*writer
, uint8_t value
)
105 return lttng_msgpack_append_buffer(writer
, &value
, sizeof(value
));
108 static inline int lttng_msgpack_append_u16(
109 struct lttng_msgpack_writer
*writer
, uint16_t value
)
111 value
= byteswap_host_to_be16(value
);
113 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
116 static inline int lttng_msgpack_append_u32(
117 struct lttng_msgpack_writer
*writer
, uint32_t value
)
119 value
= byteswap_host_to_be32(value
);
121 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
124 static inline int lttng_msgpack_append_u64(
125 struct lttng_msgpack_writer
*writer
, uint64_t value
)
127 value
= byteswap_host_to_be64(value
);
129 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
132 static inline int lttng_msgpack_append_f64(
133 struct lttng_msgpack_writer
*writer
, double value
)
143 return lttng_msgpack_append_u64(writer
, u
.u
);
146 static inline int lttng_msgpack_append_i8(
147 struct lttng_msgpack_writer
*writer
, int8_t value
)
149 return lttng_msgpack_append_u8(writer
, (uint8_t) value
);
152 static inline int lttng_msgpack_append_i16(
153 struct lttng_msgpack_writer
*writer
, int16_t value
)
155 return lttng_msgpack_append_u16(writer
, (uint16_t) value
);
158 static inline int lttng_msgpack_append_i32(
159 struct lttng_msgpack_writer
*writer
, int32_t value
)
161 return lttng_msgpack_append_u32(writer
, (uint32_t) value
);
164 static inline int lttng_msgpack_append_i64(
165 struct lttng_msgpack_writer
*writer
, int64_t value
)
167 return lttng_msgpack_append_u64(writer
, (uint64_t) value
);
170 static inline int lttng_msgpack_encode_f64(
171 struct lttng_msgpack_writer
*writer
, double value
)
175 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FLOAT64_ID
);
179 ret
= lttng_msgpack_append_f64(writer
, value
);
187 static inline int lttng_msgpack_encode_fixmap(
188 struct lttng_msgpack_writer
*writer
, uint8_t count
)
192 lttng_msgpack_assert(count
<= MSGPACK_FIXMAP_MAX_COUNT
);
194 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXMAP_ID_MASK
| count
);
202 static inline int lttng_msgpack_encode_map16(
203 struct lttng_msgpack_writer
*writer
, uint16_t count
)
207 lttng_msgpack_assert(count
> MSGPACK_FIXMAP_MAX_COUNT
);
209 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_MAP16_ID
);
213 ret
= lttng_msgpack_append_u16(writer
, count
);
221 static inline int lttng_msgpack_encode_fixarray(
222 struct lttng_msgpack_writer
*writer
, uint8_t count
)
226 lttng_msgpack_assert(count
<= MSGPACK_FIXARRAY_MAX_COUNT
);
228 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXARRAY_ID_MASK
| count
);
236 static inline int lttng_msgpack_encode_array16(
237 struct lttng_msgpack_writer
*writer
, uint16_t count
)
241 lttng_msgpack_assert(count
> MSGPACK_FIXARRAY_MAX_COUNT
);
243 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_ARRAY16_ID
);
247 ret
= lttng_msgpack_append_u16(writer
, count
);
255 static inline int lttng_msgpack_encode_fixstr(
256 struct lttng_msgpack_writer
*writer
,
262 lttng_msgpack_assert(len
<= MSGPACK_FIXSTR_MAX_LENGTH
);
264 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXSTR_ID_MASK
| len
);
268 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
276 static inline int lttng_msgpack_encode_str16(
277 struct lttng_msgpack_writer
*writer
,
283 lttng_msgpack_assert(len
> MSGPACK_FIXSTR_MAX_LENGTH
);
285 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_STR16_ID
);
289 ret
= lttng_msgpack_append_u16(writer
, len
);
293 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
301 int lttng_msgpack_begin_map(struct lttng_msgpack_writer
*writer
, size_t count
)
305 if (count
>= (1 << 16)) {
310 if (count
<= MSGPACK_FIXMAP_MAX_COUNT
)
311 ret
= lttng_msgpack_encode_fixmap(writer
, count
);
313 ret
= lttng_msgpack_encode_map16(writer
, count
);
315 writer
->map_nesting
++;
320 int lttng_msgpack_end_map(struct lttng_msgpack_writer
*writer
)
322 lttng_msgpack_assert(writer
->map_nesting
> 0);
323 writer
->map_nesting
--;
327 int lttng_msgpack_begin_array(
328 struct lttng_msgpack_writer
*writer
, size_t count
)
332 if (count
>= (1 << 16)) {
337 if (count
<= MSGPACK_FIXARRAY_MAX_COUNT
)
338 ret
= lttng_msgpack_encode_fixarray(writer
, count
);
340 ret
= lttng_msgpack_encode_array16(writer
, count
);
342 writer
->array_nesting
++;
347 int lttng_msgpack_end_array(struct lttng_msgpack_writer
*writer
)
349 lttng_msgpack_assert(writer
->array_nesting
> 0);
350 writer
->array_nesting
--;
354 int lttng_msgpack_write_str(struct lttng_msgpack_writer
*writer
,
358 size_t length
= strlen(str
);
360 if (length
>= (1 << 16)) {
365 if (length
<= MSGPACK_FIXSTR_MAX_LENGTH
)
366 ret
= lttng_msgpack_encode_fixstr(writer
, str
, length
);
368 ret
= lttng_msgpack_encode_str16(writer
, str
, length
);
374 int lttng_msgpack_write_nil(struct lttng_msgpack_writer
*writer
)
376 return lttng_msgpack_append_u8(writer
, MSGPACK_NIL_ID
);
379 int lttng_msgpack_write_true(struct lttng_msgpack_writer
*writer
)
381 return lttng_msgpack_append_u8(writer
, MSGPACK_TRUE_ID
);
384 int lttng_msgpack_write_false(struct lttng_msgpack_writer
*writer
)
386 return lttng_msgpack_append_u8(writer
, MSGPACK_FALSE_ID
);
389 int lttng_msgpack_write_unsigned_integer(
390 struct lttng_msgpack_writer
*writer
, uint64_t value
)
394 if (value
<= MSGPACK_FIXINT_MAX
) {
395 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
398 } else if (value
<= UINT8_MAX
) {
399 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT8_ID
);
403 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
406 } else if (value
<= UINT16_MAX
) {
407 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT16_ID
);
411 ret
= lttng_msgpack_append_u16(writer
, (uint16_t) value
);
414 } else if (value
<= UINT32_MAX
) {
415 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT32_ID
);
419 ret
= lttng_msgpack_append_u32(writer
, (uint32_t) value
);
423 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT64_ID
);
427 ret
= lttng_msgpack_append_u64(writer
, value
);
436 int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer
*writer
, int64_t value
)
440 if (value
>= MSGPACK_FIXINT_MIN
&& value
<= MSGPACK_FIXINT_MAX
){
441 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
444 } else if (value
>= INT8_MIN
&& value
<= INT8_MAX
) {
445 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT8_ID
);
449 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
452 } else if (value
>= INT16_MIN
&& value
<= INT16_MAX
) {
453 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT16_ID
);
457 ret
= lttng_msgpack_append_i16(writer
, (int16_t) value
);
460 } else if (value
>= INT32_MIN
&& value
<= INT32_MAX
) {
461 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT32_ID
);
465 ret
= lttng_msgpack_append_i32(writer
, (int32_t) value
);
469 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT64_ID
);
473 ret
= lttng_msgpack_append_i64(writer
, value
);
482 int lttng_msgpack_write_double(struct lttng_msgpack_writer
*writer
, double value
)
484 return lttng_msgpack_encode_f64(writer
, value
);
487 void lttng_msgpack_writer_init(struct lttng_msgpack_writer
*writer
,
488 uint8_t *buffer
, size_t size
)
490 lttng_msgpack_assert(buffer
);
491 lttng_msgpack_assert(size
>= 0);
493 writer
->buffer
= buffer
;
494 writer
->write_pos
= buffer
;
495 writer
->end_write_pos
= buffer
+ size
;
497 writer
->array_nesting
= 0;
498 writer
->map_nesting
= 0;
501 void lttng_msgpack_writer_fini(struct lttng_msgpack_writer
*writer
)
503 memset(writer
, 0, sizeof(*writer
));