cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / ctfser / ctfser.h
CommitLineData
013f35c6 1/*
0235b0db
MJ
2 * SPDX-License-Identifier: MIT
3 *
013f35c6
PP
4 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
5 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * Copyright 2017-2019 Philippe Proulx <pproulx@efficios.com>
7 *
013f35c6
PP
8 * The Common Trace Format (CTF) Specification is available at
9 * http://www.efficios.com/ctf
10 */
11
0235b0db
MJ
12#ifndef BABELTRACE_CTFSER_INTERNAL_H
13#define BABELTRACE_CTFSER_INTERNAL_H
14
c4f23e30 15#include <stdbool.h>
013f35c6
PP
16#include <stdlib.h>
17#include <stdint.h>
18#include <limits.h>
578e048b 19#include "compat/mman.h"
013f35c6
PP
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
578e048b
MJ
23#include "common/align.h"
24#include "compat/endian.h"
25#include "common/common.h"
26#include "common/mmap-align.h"
578e048b 27#include "common/assert.h"
91d81473 28#include "common/macros.h"
578e048b 29#include "compat/bitfield.h"
013f35c6
PP
30#include <glib.h>
31
32struct bt_ctfser {
33 /* Stream file's descriptor */
34 int fd;
35
36 /* Offset (bytes) of memory map (current packet) in the stream file */
37 off_t mmap_offset;
38
39 /* Offset (bytes) of packet's first byte in the memory map */
40 off_t mmap_base_offset;
41
42 /* Current offset (bits) within current packet */
43 uint64_t offset_in_cur_packet_bits;
44
45 /* Current packet size (bytes) */
46 uint64_t cur_packet_size_bytes;
47
48 /* Previous packet size (bytes) */
49 uint64_t prev_packet_size_bytes;
50
51 /* Current stream size (bytes) */
52 uint64_t stream_size_bytes;
53
54 /* Memory map base address */
443dc632 55 struct mmap_align_data *base_mma;
013f35c6
PP
56
57 /* Stream file's path (for debugging) */
58 GString *path;
86d8b7b8
PP
59
60 /* Serializer's log level */
61 int log_level;
013f35c6
PP
62};
63
013f35c6
PP
64/*
65 * Initializes a CTF serializer.
66 *
67 * This function opens the file `path` for writing.
68 */
1353b066 69BT_EXTERN_C
86d8b7b8
PP
70int bt_ctfser_init(struct bt_ctfser *ctfser, const char *path,
71 int log_level);
013f35c6
PP
72
73/*
74 * Finalizes a CTF serializer.
75 *
76 * This function truncates the stream file so that there's no extra
77 * padding after the last packet, and then closes the file.
78 */
1353b066 79BT_EXTERN_C
013f35c6
PP
80int bt_ctfser_fini(struct bt_ctfser *ctfser);
81
82/*
83 * Opens a new packet.
84 *
85 * All the next writing functions are performed within this new packet.
86 */
1353b066 87BT_EXTERN_C
013f35c6
PP
88int bt_ctfser_open_packet(struct bt_ctfser *ctfser);
89
90/*
91 * Closes the current packet, making its size `packet_size_bytes`.
92 */
1353b066 93BT_EXTERN_C
013f35c6
PP
94void bt_ctfser_close_current_packet(struct bt_ctfser *ctfser,
95 uint64_t packet_size_bytes);
96
1353b066 97BT_EXTERN_C
013f35c6
PP
98int _bt_ctfser_increase_cur_packet_size(struct bt_ctfser *ctfser);
99
100static inline
101uint64_t _bt_ctfser_cur_packet_size_bits(struct bt_ctfser *ctfser)
102{
103 return ctfser->cur_packet_size_bytes * 8;
104}
105
106static inline
107uint64_t _bt_ctfser_prev_packet_size_bits(struct bt_ctfser *ctfser)
108{
109 return ctfser->prev_packet_size_bytes * 8;
110}
111
112static inline
113uint64_t _bt_ctfser_offset_bytes(struct bt_ctfser *ctfser)
114{
115 return ctfser->offset_in_cur_packet_bits / 8;
116}
117
118static inline
119uint8_t *_bt_ctfser_get_addr(struct bt_ctfser *ctfser)
120{
121 /* Only makes sense to get the address after aligning on byte */
98b15851 122 BT_ASSERT_DBG(ctfser->offset_in_cur_packet_bits % 8 == 0);
013f35c6
PP
123 return ((uint8_t *) mmap_align_addr(ctfser->base_mma)) +
124 ctfser->mmap_base_offset + _bt_ctfser_offset_bytes(ctfser);
125}
126
127static inline
128bool _bt_ctfser_has_space_left(struct bt_ctfser *ctfser, uint64_t size_bits)
129{
130 bool has_space_left = true;
131
91d81473 132 if (G_UNLIKELY((ctfser->offset_in_cur_packet_bits + size_bits >
013f35c6
PP
133 _bt_ctfser_cur_packet_size_bits(ctfser)))) {
134 has_space_left = false;
135 goto end;
136 }
137
91d81473 138 if (G_UNLIKELY(size_bits > UINT64_MAX - ctfser->offset_in_cur_packet_bits)) {
013f35c6
PP
139 has_space_left = false;
140 goto end;
141 }
142
143end:
144 return has_space_left;
145}
146
147static inline
148void _bt_ctfser_incr_offset(struct bt_ctfser *ctfser, uint64_t size_bits)
149{
98b15851 150 BT_ASSERT_DBG(_bt_ctfser_has_space_left(ctfser, size_bits));
013f35c6
PP
151 ctfser->offset_in_cur_packet_bits += size_bits;
152}
153
154/*
155 * Aligns the current offset within the current packet to
156 * `alignment_bits` bits (power of two, > 0).
157 */
158static inline
159int bt_ctfser_align_offset_in_current_packet(struct bt_ctfser *ctfser,
160 uint64_t alignment_bits)
161{
162 int ret = 0;
163 uint64_t align_size_bits;
164
98b15851 165 BT_ASSERT_DBG(alignment_bits > 0);
328342cd 166 align_size_bits = BT_ALIGN(ctfser->offset_in_cur_packet_bits,
013f35c6
PP
167 alignment_bits) - ctfser->offset_in_cur_packet_bits;
168
91d81473 169 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, align_size_bits))) {
013f35c6 170 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
91d81473 171 if (G_UNLIKELY(ret)) {
013f35c6
PP
172 goto end;
173 }
174 }
175
176 _bt_ctfser_incr_offset(ctfser, align_size_bits);
177
178end:
179 return ret;
180}
181
182static inline
d6981059
PP
183int _bt_ctfser_write_byte_aligned_unsigned_int_no_align(
184 struct bt_ctfser *ctfser, uint64_t value,
185 unsigned int size_bits, int byte_order)
013f35c6
PP
186{
187 int ret = 0;
188
189 /* Reverse byte order? */
190 bool rbo = byte_order != BYTE_ORDER;
191
98b15851
PP
192 BT_ASSERT_DBG(size_bits % 8 == 0);
193 BT_ASSERT_DBG(_bt_ctfser_has_space_left(ctfser, size_bits));
013f35c6 194
d6981059
PP
195 switch (size_bits) {
196 case 8:
197 {
198 uint8_t v = (uint8_t) value;
199
200 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
201 break;
202 }
203 case 16:
204 {
205 uint16_t v = (uint16_t) value;
013f35c6 206
d6981059
PP
207 if (rbo) {
208 v = GUINT16_SWAP_LE_BE(v);
013f35c6 209 }
013f35c6 210
d6981059
PP
211 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
212 break;
213 }
214 case 32:
215 {
216 uint32_t v = (uint32_t) value;
013f35c6 217
d6981059
PP
218 if (rbo) {
219 v = GUINT32_SWAP_LE_BE(v);
013f35c6 220 }
013f35c6 221
d6981059
PP
222 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
223 break;
224 }
225 case 64:
226 {
227 uint64_t v = (uint64_t) value;
013f35c6 228
d6981059
PP
229 if (rbo) {
230 v = GUINT64_SWAP_LE_BE(v);
013f35c6 231 }
013f35c6 232
d6981059
PP
233 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
234 break;
235 }
236 default:
498e7994 237 bt_common_abort();
d6981059 238 }
013f35c6 239
d6981059
PP
240 _bt_ctfser_incr_offset(ctfser, size_bits);
241 return ret;
242}
013f35c6 243
d6981059
PP
244static inline
245int _bt_ctfser_write_byte_aligned_signed_int_no_align(
246 struct bt_ctfser *ctfser, int64_t value,
247 unsigned int size_bits, int byte_order)
248{
249 int ret = 0;
013f35c6 250
d6981059
PP
251 /* Reverse byte order? */
252 bool rbo = byte_order != BYTE_ORDER;
013f35c6 253
98b15851
PP
254 BT_ASSERT_DBG(size_bits % 8 == 0);
255 BT_ASSERT_DBG(_bt_ctfser_has_space_left(ctfser, size_bits));
013f35c6 256
d6981059
PP
257 switch (size_bits) {
258 case 8:
259 {
260 int8_t v = (int8_t) value;
013f35c6 261
d6981059
PP
262 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
263 break;
264 }
265 case 16:
266 {
267 int16_t v = (int16_t) value;
268
269 if (rbo) {
270 v = GUINT16_SWAP_LE_BE(v);
013f35c6 271 }
013f35c6 272
d6981059
PP
273 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
274 break;
275 }
276 case 32:
277 {
278 int32_t v = (int32_t) value;
013f35c6 279
d6981059
PP
280 if (rbo) {
281 v = GUINT32_SWAP_LE_BE(v);
013f35c6 282 }
d6981059
PP
283
284 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
285 break;
286 }
287 case 64:
288 {
289 int64_t v = (int64_t) value;
290
291 if (rbo) {
292 v = GUINT64_SWAP_LE_BE(v);
013f35c6 293 }
d6981059
PP
294
295 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
296 break;
297 }
298 default:
498e7994 299 bt_common_abort();
013f35c6
PP
300 }
301
302 _bt_ctfser_incr_offset(ctfser, size_bits);
303 return ret;
304}
305
306/*
d6981059
PP
307 * Writes an unsigned integer known to have a size that is a multiple of
308 * 8 and an alignment that is >= 8 at the current offset within the
309 * current packet.
013f35c6
PP
310 */
311static inline
d6981059
PP
312int bt_ctfser_write_byte_aligned_unsigned_int(struct bt_ctfser *ctfser,
313 uint64_t value, unsigned int alignment_bits,
314 unsigned int size_bits, int byte_order)
013f35c6
PP
315{
316 int ret;
317
98b15851 318 BT_ASSERT_DBG(alignment_bits % 8 == 0);
013f35c6 319 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
91d81473 320 if (G_UNLIKELY(ret)) {
013f35c6
PP
321 goto end;
322 }
323
91d81473 324 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
013f35c6 325 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
91d81473 326 if (G_UNLIKELY(ret)) {
013f35c6
PP
327 goto end;
328 }
329 }
330
d6981059
PP
331 ret = _bt_ctfser_write_byte_aligned_unsigned_int_no_align(ctfser, value,
332 size_bits, byte_order);
91d81473 333 if (G_UNLIKELY(ret)) {
013f35c6
PP
334 goto end;
335 }
336
337end:
338 return ret;
339}
340
341/*
d6981059
PP
342 * Writes a signed integer known to have a size that is a multiple of 8
343 * and an alignment that is >= 8 at the current offset within the
344 * current packet.
013f35c6
PP
345 */
346static inline
d6981059
PP
347int bt_ctfser_write_byte_aligned_signed_int(struct bt_ctfser *ctfser,
348 int64_t value, unsigned int alignment_bits,
349 unsigned int size_bits, int byte_order)
350{
351 int ret;
352
98b15851 353 BT_ASSERT_DBG(alignment_bits % 8 == 0);
d6981059 354 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
91d81473 355 if (G_UNLIKELY(ret)) {
d6981059
PP
356 goto end;
357 }
358
91d81473 359 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
d6981059 360 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
91d81473 361 if (G_UNLIKELY(ret)) {
d6981059
PP
362 goto end;
363 }
364 }
365
366 ret = _bt_ctfser_write_byte_aligned_signed_int_no_align(ctfser, value,
367 size_bits, byte_order);
91d81473 368 if (G_UNLIKELY(ret)) {
d6981059
PP
369 goto end;
370 }
371
372end:
373 return ret;
374}
375
376/*
377 * Writes an unsigned integer at the current offset within the current
378 * packet.
379 */
380static inline
381int bt_ctfser_write_unsigned_int(struct bt_ctfser *ctfser, uint64_t value,
382 unsigned int alignment_bits, unsigned int size_bits,
013f35c6
PP
383 int byte_order)
384{
385 int ret = 0;
386
387 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
91d81473 388 if (G_UNLIKELY(ret)) {
013f35c6
PP
389 goto end;
390 }
391
91d81473 392 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
013f35c6 393 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
91d81473 394 if (G_UNLIKELY(ret)) {
013f35c6
PP
395 goto end;
396 }
397 }
398
399 if (alignment_bits % 8 == 0 && size_bits % 8 == 0) {
d6981059
PP
400 ret = _bt_ctfser_write_byte_aligned_unsigned_int_no_align(
401 ctfser, value, size_bits, byte_order);
013f35c6
PP
402 goto end;
403 }
404
d6981059 405 if (byte_order == LITTLE_ENDIAN) {
087cd0f5 406 bt_bitfield_write_le((uint8_t *) mmap_align_addr(ctfser->base_mma) +
d6981059
PP
407 ctfser->mmap_base_offset, uint8_t,
408 ctfser->offset_in_cur_packet_bits, size_bits, value);
013f35c6 409 } else {
087cd0f5 410 bt_bitfield_write_be((uint8_t *) mmap_align_addr(ctfser->base_mma) +
d6981059
PP
411 ctfser->mmap_base_offset, uint8_t,
412 ctfser->offset_in_cur_packet_bits, size_bits, value);
413 }
414
415 _bt_ctfser_incr_offset(ctfser, size_bits);
416
417end:
418 return ret;
419}
420
421/*
422 * Writes a signed integer at the current offset within the current
423 * packet.
424 */
425static inline
426int bt_ctfser_write_signed_int(struct bt_ctfser *ctfser, int64_t value,
427 unsigned int alignment_bits, unsigned int size_bits,
428 int byte_order)
429{
430 int ret = 0;
431
432 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
91d81473 433 if (G_UNLIKELY(ret)) {
d6981059
PP
434 goto end;
435 }
436
91d81473 437 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
d6981059 438 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
91d81473 439 if (G_UNLIKELY(ret)) {
d6981059 440 goto end;
013f35c6
PP
441 }
442 }
443
d6981059
PP
444 if (alignment_bits % 8 == 0 && size_bits % 8 == 0) {
445 ret = _bt_ctfser_write_byte_aligned_signed_int_no_align(
446 ctfser, value, size_bits, byte_order);
447 goto end;
448 }
449
450 if (byte_order == LITTLE_ENDIAN) {
087cd0f5 451 bt_bitfield_write_le((uint8_t *) mmap_align_addr(ctfser->base_mma) +
d6981059
PP
452 ctfser->mmap_base_offset, uint8_t,
453 ctfser->offset_in_cur_packet_bits, size_bits, value);
454 } else {
087cd0f5 455 bt_bitfield_write_be((uint8_t *) mmap_align_addr(ctfser->base_mma) +
d6981059
PP
456 ctfser->mmap_base_offset, uint8_t,
457 ctfser->offset_in_cur_packet_bits, size_bits, value);
458 }
459
013f35c6
PP
460 _bt_ctfser_incr_offset(ctfser, size_bits);
461
462end:
463 return ret;
464}
465
466/*
467 * Writes a 32-bit floating point number at the current offset within
468 * the current packet.
469 */
470static inline
471int bt_ctfser_write_float32(struct bt_ctfser *ctfser, double value,
472 unsigned int alignment_bits, int byte_order)
473{
013f35c6
PP
474 union u32f {
475 uint32_t u;
476 float f;
477 } u32f;
478
479 u32f.f = (float) value;
d6981059
PP
480 return bt_ctfser_write_unsigned_int(ctfser, (uint64_t) u32f.u,
481 alignment_bits, 32, byte_order);
013f35c6
PP
482}
483
484/*
485 * Writes a 64-bit floating point number at the current offset within
486 * the current packet.
487 */
488static inline
489int bt_ctfser_write_float64(struct bt_ctfser *ctfser, double value,
490 unsigned int alignment_bits, int byte_order)
491{
013f35c6
PP
492 union u64f {
493 uint64_t u;
1fba7c7b 494 double d;
013f35c6
PP
495 } u64f;
496
1fba7c7b 497 u64f.d = value;
d6981059
PP
498 return bt_ctfser_write_unsigned_int(ctfser, u64f.u, alignment_bits,
499 64, byte_order);
013f35c6
PP
500}
501
502/*
503 * Writes a C string, including the terminating null character, at the
504 * current offset within the current packet.
505 */
506static inline
507int bt_ctfser_write_string(struct bt_ctfser *ctfser, const char *value)
508{
509 int ret = 0;
510 const char *at = value;
511
512 ret = bt_ctfser_align_offset_in_current_packet(ctfser, 8);
91d81473 513 if (G_UNLIKELY(ret)) {
013f35c6
PP
514 goto end;
515 }
516
517 while (true) {
91d81473 518 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, 8))) {
013f35c6 519 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
91d81473 520 if (G_UNLIKELY(ret)) {
013f35c6
PP
521 goto end;
522 }
523 }
524
525 memcpy(_bt_ctfser_get_addr(ctfser), at, sizeof(*at));
526 _bt_ctfser_incr_offset(ctfser, 8);
527
91d81473 528 if (G_UNLIKELY(*at == '\0')) {
013f35c6
PP
529 break;
530 }
531
532 at++;
533 }
534
535end:
536 return ret;
537}
538
539/*
540 * Returns the current offset within the current packet (bits).
541 */
542static inline
543uint64_t bt_ctfser_get_offset_in_current_packet_bits(struct bt_ctfser *ctfser)
544{
545 return ctfser->offset_in_cur_packet_bits;
546}
547
548/*
549 * Sets the current offset within the current packet (bits).
550 */
551static inline
552void bt_ctfser_set_offset_in_current_packet_bits(struct bt_ctfser *ctfser,
553 uint64_t offset_bits)
554{
98b15851 555 BT_ASSERT_DBG(offset_bits <= _bt_ctfser_cur_packet_size_bits(ctfser));
013f35c6
PP
556 ctfser->offset_in_cur_packet_bits = offset_bits;
557}
558
15fe47e0
PP
559static inline
560const char *bt_ctfser_get_file_path(struct bt_ctfser *ctfser)
561{
562 return ctfser->path->str;
563}
564
013f35c6 565#endif /* BABELTRACE_CTFSER_INTERNAL_H */
This page took 0.108466 seconds and 4 git commands to generate.