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