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