Move to kernel style SPDX license identifiers
[deliverable/lttng-ust.git] / libmsgpack / msgpack.c
CommitLineData
49705576 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
49705576
FD
3 *
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
49705576
FD
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
f03092d7 65#include <lttng/ust-endian.h>
49705576
FD
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
81static 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;
98end:
99 return ret;
100}
101
102static 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
108static 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
116static 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
124static 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
132static 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
146static 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
152static 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
158static 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
164static 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
170static 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
183end:
184 return ret;
185}
186
187static 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
198end:
199 return ret;
200}
201
202static 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
217end:
218 return ret;
219}
220
221static 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
232end:
233 return ret;
234}
235
236static 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
251end:
252 return ret;
253}
254
255static 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
272end:
273 return ret;
274}
275
276static 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
297end:
298 return ret;
299}
300
301int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count)
302{
303 int ret;
304
8b914423 305 if (count >= (1 << 16)) {
49705576
FD
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++;
316end:
317 return ret;
318}
319
320int 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
327int lttng_msgpack_begin_array(
328 struct lttng_msgpack_writer *writer, size_t count)
329{
330 int ret;
331
8b914423 332 if (count >= (1 << 16)) {
49705576
FD
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++;
343end:
344 return ret;
345}
346
347int 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
354int lttng_msgpack_write_str(struct lttng_msgpack_writer *writer,
355 const char *str)
356{
357 int ret;
358 size_t length = strlen(str);
8b914423
MD
359
360 if (length >= (1 << 16)) {
49705576
FD
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
370end:
371 return ret;
372}
373
374int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer)
375{
376 return lttng_msgpack_append_u8(writer, MSGPACK_NIL_ID);
377}
378
379int lttng_msgpack_write_true(struct lttng_msgpack_writer *writer)
380{
381 return lttng_msgpack_append_u8(writer, MSGPACK_TRUE_ID);
382}
383
384int lttng_msgpack_write_false(struct lttng_msgpack_writer *writer)
385{
386 return lttng_msgpack_append_u8(writer, MSGPACK_FALSE_ID);
387}
388
389int 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
432end:
433 return ret;
434}
435
436int 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
478end:
479 return ret;
480}
481
482int lttng_msgpack_write_double(struct lttng_msgpack_writer *writer, double value)
483{
484 return lttng_msgpack_encode_f64(writer, value);
485}
486
487void 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
501void lttng_msgpack_writer_fini(struct lttng_msgpack_writer *writer)
502{
503 memset(writer, 0, sizeof(*writer));
504}
This page took 0.042864 seconds and 5 git commands to generate.