Move to kernel style SPDX license identifiers
[lttng-ust.git] / libmsgpack / msgpack.c
1 /*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
5 */
6
7 #define _GNU_SOURCE
8 #define _LGPL_SOURCE
9 #include <stddef.h>
10
11 #define MSGPACK_FIXSTR_ID_MASK 0xA0
12 #define MSGPACK_FIXMAP_ID_MASK 0x80
13 #define MSGPACK_FIXARRAY_ID_MASK 0x90
14
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
20
21 #define MSGPACK_UINT8_ID 0xCC
22 #define MSGPACK_UINT16_ID 0xCD
23 #define MSGPACK_UINT32_ID 0xCE
24 #define MSGPACK_UINT64_ID 0xCF
25
26 #define MSGPACK_INT8_ID 0xD0
27 #define MSGPACK_INT16_ID 0xD1
28 #define MSGPACK_INT32_ID 0xD2
29 #define MSGPACK_INT64_ID 0xD3
30
31 #define MSGPACK_FLOAT64_ID 0xCB
32 #define MSGPACK_STR16_ID 0xDA
33
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
39
40 #ifdef __KERNEL__
41 #include <linux/bug.h>
42 #include <linux/string.h>
43 #include <linux/types.h>
44
45 #include <lttng/msgpack.h>
46
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)
56
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)
60
61 #define lttng_msgpack_assert(cond) WARN_ON(!(cond))
62
63 #else /* __KERNEL__ */
64
65 #include <lttng/ust-endian.h>
66 #include <stdio.h>
67 #include <string.h>
68
69 #include "msgpack.h"
70
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)
74
75 #define lttng_msgpack_assert(cond) ({ \
76 if (!(cond)) \
77 fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
78 })
79 #endif /* __KERNEL__ */
80
81 static inline int lttng_msgpack_append_buffer(
82 struct lttng_msgpack_writer *writer,
83 const uint8_t *buf,
84 size_t length)
85 {
86 int ret = 0;
87
88 lttng_msgpack_assert(buf);
89
90 /* Ensure we are not trying to write after the end of the buffer. */
91 if (writer->write_pos + length > writer->end_write_pos) {
92 ret = -1;
93 goto end;
94 }
95
96 memcpy(writer->write_pos, buf, length);
97 writer->write_pos += length;
98 end:
99 return ret;
100 }
101
102 static inline int lttng_msgpack_append_u8(
103 struct lttng_msgpack_writer *writer, uint8_t value)
104 {
105 return lttng_msgpack_append_buffer(writer, &value, sizeof(value));
106 }
107
108 static inline int lttng_msgpack_append_u16(
109 struct lttng_msgpack_writer *writer, uint16_t value)
110 {
111 value = byteswap_host_to_be16(value);
112
113 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
114 }
115
116 static inline int lttng_msgpack_append_u32(
117 struct lttng_msgpack_writer *writer, uint32_t value)
118 {
119 value = byteswap_host_to_be32(value);
120
121 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
122 }
123
124 static inline int lttng_msgpack_append_u64(
125 struct lttng_msgpack_writer *writer, uint64_t value)
126 {
127 value = byteswap_host_to_be64(value);
128
129 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
130 }
131
132 static inline int lttng_msgpack_append_f64(
133 struct lttng_msgpack_writer *writer, double value)
134 {
135
136 union {
137 double d;
138 uint64_t u;
139 } u;
140
141 u.d = value;
142
143 return lttng_msgpack_append_u64(writer, u.u);
144 }
145
146 static inline int lttng_msgpack_append_i8(
147 struct lttng_msgpack_writer *writer, int8_t value)
148 {
149 return lttng_msgpack_append_u8(writer, (uint8_t) value);
150 }
151
152 static inline int lttng_msgpack_append_i16(
153 struct lttng_msgpack_writer *writer, int16_t value)
154 {
155 return lttng_msgpack_append_u16(writer, (uint16_t) value);
156 }
157
158 static inline int lttng_msgpack_append_i32(
159 struct lttng_msgpack_writer *writer, int32_t value)
160 {
161 return lttng_msgpack_append_u32(writer, (uint32_t) value);
162 }
163
164 static inline int lttng_msgpack_append_i64(
165 struct lttng_msgpack_writer *writer, int64_t value)
166 {
167 return lttng_msgpack_append_u64(writer, (uint64_t) value);
168 }
169
170 static inline int lttng_msgpack_encode_f64(
171 struct lttng_msgpack_writer *writer, double value)
172 {
173 int ret;
174
175 ret = lttng_msgpack_append_u8(writer, MSGPACK_FLOAT64_ID);
176 if (ret)
177 goto end;
178
179 ret = lttng_msgpack_append_f64(writer, value);
180 if (ret)
181 goto end;
182
183 end:
184 return ret;
185 }
186
187 static inline int lttng_msgpack_encode_fixmap(
188 struct lttng_msgpack_writer *writer, uint8_t count)
189 {
190 int ret = 0;
191
192 lttng_msgpack_assert(count <= MSGPACK_FIXMAP_MAX_COUNT);
193
194 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXMAP_ID_MASK | count);
195 if (ret)
196 goto end;
197
198 end:
199 return ret;
200 }
201
202 static inline int lttng_msgpack_encode_map16(
203 struct lttng_msgpack_writer *writer, uint16_t count)
204 {
205 int ret;
206
207 lttng_msgpack_assert(count > MSGPACK_FIXMAP_MAX_COUNT);
208
209 ret = lttng_msgpack_append_u8(writer, MSGPACK_MAP16_ID);
210 if (ret)
211 goto end;
212
213 ret = lttng_msgpack_append_u16(writer, count);
214 if (ret)
215 goto end;
216
217 end:
218 return ret;
219 }
220
221 static inline int lttng_msgpack_encode_fixarray(
222 struct lttng_msgpack_writer *writer, uint8_t count)
223 {
224 int ret = 0;
225
226 lttng_msgpack_assert(count <= MSGPACK_FIXARRAY_MAX_COUNT);
227
228 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXARRAY_ID_MASK | count);
229 if (ret)
230 goto end;
231
232 end:
233 return ret;
234 }
235
236 static inline int lttng_msgpack_encode_array16(
237 struct lttng_msgpack_writer *writer, uint16_t count)
238 {
239 int ret;
240
241 lttng_msgpack_assert(count > MSGPACK_FIXARRAY_MAX_COUNT);
242
243 ret = lttng_msgpack_append_u8(writer, MSGPACK_ARRAY16_ID);
244 if (ret)
245 goto end;
246
247 ret = lttng_msgpack_append_u16(writer, count);
248 if (ret)
249 goto end;
250
251 end:
252 return ret;
253 }
254
255 static inline int lttng_msgpack_encode_fixstr(
256 struct lttng_msgpack_writer *writer,
257 const char *str,
258 uint8_t len)
259 {
260 int ret;
261
262 lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
263
264 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
265 if (ret)
266 goto end;
267
268 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
269 if (ret)
270 goto end;
271
272 end:
273 return ret;
274 }
275
276 static inline int lttng_msgpack_encode_str16(
277 struct lttng_msgpack_writer *writer,
278 const char *str,
279 uint16_t len)
280 {
281 int ret;
282
283 lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
284
285 ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
286 if (ret)
287 goto end;
288
289 ret = lttng_msgpack_append_u16(writer, len);
290 if (ret)
291 goto end;
292
293 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
294 if (ret)
295 goto end;
296
297 end:
298 return ret;
299 }
300
301 int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count)
302 {
303 int ret;
304
305 if (count >= (1 << 16)) {
306 ret = -1;
307 goto end;
308 }
309
310 if (count <= MSGPACK_FIXMAP_MAX_COUNT)
311 ret = lttng_msgpack_encode_fixmap(writer, count);
312 else
313 ret = lttng_msgpack_encode_map16(writer, count);
314
315 writer->map_nesting++;
316 end:
317 return ret;
318 }
319
320 int lttng_msgpack_end_map(struct lttng_msgpack_writer *writer)
321 {
322 lttng_msgpack_assert(writer->map_nesting > 0);
323 writer->map_nesting--;
324 return 0;
325 }
326
327 int lttng_msgpack_begin_array(
328 struct lttng_msgpack_writer *writer, size_t count)
329 {
330 int ret;
331
332 if (count >= (1 << 16)) {
333 ret = -1;
334 goto end;
335 }
336
337 if (count <= MSGPACK_FIXARRAY_MAX_COUNT)
338 ret = lttng_msgpack_encode_fixarray(writer, count);
339 else
340 ret = lttng_msgpack_encode_array16(writer, count);
341
342 writer->array_nesting++;
343 end:
344 return ret;
345 }
346
347 int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer)
348 {
349 lttng_msgpack_assert(writer->array_nesting > 0);
350 writer->array_nesting--;
351 return 0;
352 }
353
354 int lttng_msgpack_write_str(struct lttng_msgpack_writer *writer,
355 const char *str)
356 {
357 int ret;
358 size_t length = strlen(str);
359
360 if (length >= (1 << 16)) {
361 ret = -1;
362 goto end;
363 }
364
365 if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
366 ret = lttng_msgpack_encode_fixstr(writer, str, length);
367 else
368 ret = lttng_msgpack_encode_str16(writer, str, length);
369
370 end:
371 return ret;
372 }
373
374 int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer)
375 {
376 return lttng_msgpack_append_u8(writer, MSGPACK_NIL_ID);
377 }
378
379 int lttng_msgpack_write_true(struct lttng_msgpack_writer *writer)
380 {
381 return lttng_msgpack_append_u8(writer, MSGPACK_TRUE_ID);
382 }
383
384 int lttng_msgpack_write_false(struct lttng_msgpack_writer *writer)
385 {
386 return lttng_msgpack_append_u8(writer, MSGPACK_FALSE_ID);
387 }
388
389 int lttng_msgpack_write_unsigned_integer(
390 struct lttng_msgpack_writer *writer, uint64_t value)
391 {
392 int ret = 0;
393
394 if (value <= MSGPACK_FIXINT_MAX) {
395 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
396 if (ret)
397 goto end;
398 } else if (value <= UINT8_MAX) {
399 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT8_ID);
400 if (ret)
401 goto end;
402
403 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
404 if (ret)
405 goto end;
406 } else if (value <= UINT16_MAX) {
407 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT16_ID);
408 if (ret)
409 goto end;
410
411 ret = lttng_msgpack_append_u16(writer, (uint16_t) value);
412 if (ret)
413 goto end;
414 } else if (value <= UINT32_MAX) {
415 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT32_ID);
416 if (ret)
417 goto end;
418
419 ret = lttng_msgpack_append_u32(writer, (uint32_t) value);
420 if (ret)
421 goto end;
422 } else {
423 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT64_ID);
424 if (ret)
425 goto end;
426
427 ret = lttng_msgpack_append_u64(writer, value);
428 if (ret)
429 goto end;
430 }
431
432 end:
433 return ret;
434 }
435
436 int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer *writer, int64_t value)
437 {
438 int ret;
439
440 if (value >= MSGPACK_FIXINT_MIN && value <= MSGPACK_FIXINT_MAX){
441 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
442 if (ret)
443 goto end;
444 } else if (value >= INT8_MIN && value <= INT8_MAX) {
445 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT8_ID);
446 if (ret)
447 goto end;
448
449 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
450 if (ret)
451 goto end;
452 } else if (value >= INT16_MIN && value <= INT16_MAX) {
453 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT16_ID);
454 if (ret)
455 goto end;
456
457 ret = lttng_msgpack_append_i16(writer, (int16_t) value);
458 if (ret)
459 goto end;
460 } else if (value >= INT32_MIN && value <= INT32_MAX) {
461 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT32_ID);
462 if (ret)
463 goto end;
464
465 ret = lttng_msgpack_append_i32(writer, (int32_t) value);
466 if (ret)
467 goto end;
468 } else {
469 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT64_ID);
470 if (ret)
471 goto end;
472
473 ret = lttng_msgpack_append_i64(writer, value);
474 if (ret)
475 goto end;
476 }
477
478 end:
479 return ret;
480 }
481
482 int lttng_msgpack_write_double(struct lttng_msgpack_writer *writer, double value)
483 {
484 return lttng_msgpack_encode_f64(writer, value);
485 }
486
487 void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
488 uint8_t *buffer, size_t size)
489 {
490 lttng_msgpack_assert(buffer);
491 lttng_msgpack_assert(size >= 0);
492
493 writer->buffer = buffer;
494 writer->write_pos = buffer;
495 writer->end_write_pos = buffer + size;
496
497 writer->array_nesting = 0;
498 writer->map_nesting = 0;
499 }
500
501 void lttng_msgpack_writer_fini(struct lttng_msgpack_writer *writer)
502 {
503 memset(writer, 0, sizeof(*writer));
504 }
This page took 0.039167 seconds and 4 git commands to generate.