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