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