b4d9beec279839ecde9aff98462ef36da5bc8a97
[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_i8(
148 struct lttng_msgpack_writer *writer, int8_t value)
149 {
150 return lttng_msgpack_append_u8(writer, (uint8_t) value);
151 }
152
153 static inline int lttng_msgpack_append_i16(
154 struct lttng_msgpack_writer *writer, int16_t value)
155 {
156 return lttng_msgpack_append_u16(writer, (uint16_t) value);
157 }
158
159 static inline int lttng_msgpack_append_i32(
160 struct lttng_msgpack_writer *writer, int32_t value)
161 {
162 return lttng_msgpack_append_u32(writer, (uint32_t) value);
163 }
164
165 static inline int lttng_msgpack_append_i64(
166 struct lttng_msgpack_writer *writer, int64_t value)
167 {
168 return lttng_msgpack_append_u64(writer, (uint64_t) value);
169 }
170
171 static inline int lttng_msgpack_encode_fixmap(
172 struct lttng_msgpack_writer *writer, uint8_t count)
173 {
174 int ret = 0;
175
176 lttng_msgpack_assert(count <= MSGPACK_FIXMAP_MAX_COUNT);
177
178 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXMAP_ID_MASK | count);
179 if (ret)
180 goto end;
181
182 end:
183 return ret;
184 }
185
186 static inline int lttng_msgpack_encode_map16(
187 struct lttng_msgpack_writer *writer, uint16_t count)
188 {
189 int ret;
190
191 lttng_msgpack_assert(count > MSGPACK_FIXMAP_MAX_COUNT);
192
193 ret = lttng_msgpack_append_u8(writer, MSGPACK_MAP16_ID);
194 if (ret)
195 goto end;
196
197 ret = lttng_msgpack_append_u16(writer, count);
198 if (ret)
199 goto end;
200
201 end:
202 return ret;
203 }
204
205 static inline int lttng_msgpack_encode_fixarray(
206 struct lttng_msgpack_writer *writer, uint8_t count)
207 {
208 int ret = 0;
209
210 lttng_msgpack_assert(count <= MSGPACK_FIXARRAY_MAX_COUNT);
211
212 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXARRAY_ID_MASK | count);
213 if (ret)
214 goto end;
215
216 end:
217 return ret;
218 }
219
220 static inline int lttng_msgpack_encode_array16(
221 struct lttng_msgpack_writer *writer, uint16_t count)
222 {
223 int ret;
224
225 lttng_msgpack_assert(count > MSGPACK_FIXARRAY_MAX_COUNT);
226
227 ret = lttng_msgpack_append_u8(writer, MSGPACK_ARRAY16_ID);
228 if (ret)
229 goto end;
230
231 ret = lttng_msgpack_append_u16(writer, count);
232 if (ret)
233 goto end;
234
235 end:
236 return ret;
237 }
238
239 static inline int lttng_msgpack_encode_fixstr(
240 struct lttng_msgpack_writer *writer,
241 const char *str,
242 uint8_t len)
243 {
244 int ret;
245
246 lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
247
248 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
249 if (ret)
250 goto end;
251
252 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
253 if (ret)
254 goto end;
255
256 end:
257 return ret;
258 }
259
260 static inline int lttng_msgpack_encode_str16(
261 struct lttng_msgpack_writer *writer,
262 const char *str,
263 uint16_t len)
264 {
265 int ret;
266
267 lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
268
269 ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
270 if (ret)
271 goto end;
272
273 ret = lttng_msgpack_append_u16(writer, len);
274 if (ret)
275 goto end;
276
277 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
278 if (ret)
279 goto end;
280
281 end:
282 return ret;
283 }
284
285 int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count)
286 {
287 int ret;
288
289 if (count >= (1 << 16)) {
290 ret = -1;
291 goto end;
292 }
293
294 if (count <= MSGPACK_FIXMAP_MAX_COUNT)
295 ret = lttng_msgpack_encode_fixmap(writer, count);
296 else
297 ret = lttng_msgpack_encode_map16(writer, count);
298
299 writer->map_nesting++;
300 end:
301 return ret;
302 }
303
304 int lttng_msgpack_end_map(struct lttng_msgpack_writer *writer)
305 {
306 lttng_msgpack_assert(writer->map_nesting > 0);
307 writer->map_nesting--;
308 return 0;
309 }
310
311 int lttng_msgpack_begin_array(
312 struct lttng_msgpack_writer *writer, size_t count)
313 {
314 int ret;
315
316 if (count >= (1 << 16)) {
317 ret = -1;
318 goto end;
319 }
320
321 if (count <= MSGPACK_FIXARRAY_MAX_COUNT)
322 ret = lttng_msgpack_encode_fixarray(writer, count);
323 else
324 ret = lttng_msgpack_encode_array16(writer, count);
325
326 writer->array_nesting++;
327 end:
328 return ret;
329 }
330
331 int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer)
332 {
333 lttng_msgpack_assert(writer->array_nesting > 0);
334 writer->array_nesting--;
335 return 0;
336 }
337
338 int lttng_msgpack_write_str(struct lttng_msgpack_writer *writer,
339 const char *str)
340 {
341 int ret;
342 size_t length = strlen(str);
343
344 if (length >= (1 << 16)) {
345 ret = -1;
346 goto end;
347 }
348
349 if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
350 ret = lttng_msgpack_encode_fixstr(writer, str, length);
351 else
352 ret = lttng_msgpack_encode_str16(writer, str, length);
353
354 end:
355 return ret;
356 }
357
358 int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer)
359 {
360 return lttng_msgpack_append_u8(writer, MSGPACK_NIL_ID);
361 }
362
363 int lttng_msgpack_write_true(struct lttng_msgpack_writer *writer)
364 {
365 return lttng_msgpack_append_u8(writer, MSGPACK_TRUE_ID);
366 }
367
368 int lttng_msgpack_write_false(struct lttng_msgpack_writer *writer)
369 {
370 return lttng_msgpack_append_u8(writer, MSGPACK_FALSE_ID);
371 }
372
373 int lttng_msgpack_write_unsigned_integer(
374 struct lttng_msgpack_writer *writer, uint64_t value)
375 {
376 int ret = 0;
377
378 if (value <= MSGPACK_FIXINT_MAX) {
379 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
380 if (ret)
381 goto end;
382 } else if (value <= UINT8_MAX) {
383 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT8_ID);
384 if (ret)
385 goto end;
386
387 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
388 if (ret)
389 goto end;
390 } else if (value <= UINT16_MAX) {
391 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT16_ID);
392 if (ret)
393 goto end;
394
395 ret = lttng_msgpack_append_u16(writer, (uint16_t) value);
396 if (ret)
397 goto end;
398 } else if (value <= UINT32_MAX) {
399 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT32_ID);
400 if (ret)
401 goto end;
402
403 ret = lttng_msgpack_append_u32(writer, (uint32_t) value);
404 if (ret)
405 goto end;
406 } else {
407 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT64_ID);
408 if (ret)
409 goto end;
410
411 ret = lttng_msgpack_append_u64(writer, value);
412 if (ret)
413 goto end;
414 }
415
416 end:
417 return ret;
418 }
419
420 int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer *writer, int64_t value)
421 {
422 int ret;
423
424 if (value >= MSGPACK_FIXINT_MIN && value <= MSGPACK_FIXINT_MAX){
425 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
426 if (ret)
427 goto end;
428 } else if (value >= INT8_MIN && value <= INT8_MAX) {
429 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT8_ID);
430 if (ret)
431 goto end;
432
433 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
434 if (ret)
435 goto end;
436 } else if (value >= INT16_MIN && value <= INT16_MAX) {
437 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT16_ID);
438 if (ret)
439 goto end;
440
441 ret = lttng_msgpack_append_i16(writer, (int16_t) value);
442 if (ret)
443 goto end;
444 } else if (value >= INT32_MIN && value <= INT32_MAX) {
445 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT32_ID);
446 if (ret)
447 goto end;
448
449 ret = lttng_msgpack_append_i32(writer, (int32_t) value);
450 if (ret)
451 goto end;
452 } else {
453 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT64_ID);
454 if (ret)
455 goto end;
456
457 ret = lttng_msgpack_append_i64(writer, value);
458 if (ret)
459 goto end;
460 }
461
462 end:
463 return ret;
464 }
465
466 void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
467 uint8_t *buffer, size_t size)
468 {
469 lttng_msgpack_assert(buffer);
470 lttng_msgpack_assert(size >= 0);
471
472 writer->buffer = buffer;
473 writer->write_pos = buffer;
474 writer->end_write_pos = buffer + size;
475
476 writer->array_nesting = 0;
477 writer->map_nesting = 0;
478 }
479
480 void lttng_msgpack_writer_fini(struct lttng_msgpack_writer *writer)
481 {
482 memset(writer, 0, sizeof(*writer));
483 }
This page took 0.042388 seconds and 3 git commands to generate.