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