Rename bt_ctf_X -> bt_X, maintain backward compat. for pre-2.0 CTF writer
[babeltrace.git] / lib / ctf-writer / serialize.c
CommitLineData
dc3fffef
PP
1/*
2 * serialize.c
3 *
4 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
5 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
7 *
8 * The original author of the serialization functions for Babeltrace 1
9 * is Mathieu Desnoyers. Philippe Proulx modified the functions in 2017
10 * to use Babeltrace 2 objects.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * SOFTWARE.
29 */
30
0fbb9a9f 31#include <stdlib.h>
dc3fffef
PP
32#include <stdio.h>
33#include <stdint.h>
dc3fffef
PP
34#include <babeltrace/ctf-ir/field-types.h>
35#include <babeltrace/ctf-ir/field-types-internal.h>
36#include <babeltrace/ctf-ir/fields.h>
37#include <babeltrace/ctf-ir/fields-internal.h>
38#include <babeltrace/ctf-writer/serialize-internal.h>
3d9990ac
PP
39#include <babeltrace/align-internal.h>
40#include <babeltrace/mmap-align-internal.h>
41#include <babeltrace/endian-internal.h>
42#include <babeltrace/bitfield-internal.h>
43#include <babeltrace/compat/fcntl-internal.h>
c55a9f58 44#include <babeltrace/types.h>
108e5a1e 45#include <babeltrace/common-internal.h>
dc3fffef
PP
46#include <glib.h>
47
dc3fffef
PP
48#if (FLT_RADIX != 2)
49# error "Unsupported floating point radix"
50#endif
51
52union intval {
53 int64_t signd;
54 uint64_t unsignd;
55};
56
57/*
58 * The aligned read/write functions are expected to be faster than the
59 * bitfield variants. They will be enabled eventually as an
60 * optimisation.
61 */
62static
50842bdc 63int aligned_integer_write(struct bt_stream_pos *pos,
dc3fffef 64 union intval value, unsigned int alignment, unsigned int size,
50842bdc 65 bt_bool is_signed, enum bt_byte_order byte_order)
dc3fffef 66{
50842bdc 67 bt_bool rbo = (byte_order != BT_MY_BYTE_ORDER); /* reverse byte order */
dc3fffef 68
50842bdc 69 if (!bt_stream_pos_align(pos, alignment))
dc3fffef
PP
70 return -EFAULT;
71
50842bdc 72 if (!bt_stream_pos_access_ok(pos, size))
dc3fffef
PP
73 return -EFAULT;
74
75 assert(!(pos->offset % CHAR_BIT));
76 if (!is_signed) {
77 switch (size) {
78 case 8:
79 {
80 uint8_t v = value.unsignd;
81
50842bdc 82 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
83 break;
84 }
85 case 16:
86 {
87 uint16_t v = value.unsignd;
88
89 if (rbo)
90 v = GUINT16_SWAP_LE_BE(v);
50842bdc 91 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
92 break;
93 }
94 case 32:
95 {
96 uint32_t v = value.unsignd;
97
98 if (rbo)
99 v = GUINT32_SWAP_LE_BE(v);
50842bdc 100 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
101 break;
102 }
103 case 64:
104 {
105 uint64_t v = value.unsignd;
106
107 if (rbo)
108 v = GUINT64_SWAP_LE_BE(v);
50842bdc 109 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
110 break;
111 }
112 default:
0fbb9a9f 113 abort();
dc3fffef
PP
114 }
115 } else {
116 switch (size) {
117 case 8:
118 {
119 uint8_t v = value.signd;
120
50842bdc 121 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
122 break;
123 }
124 case 16:
125 {
126 int16_t v = value.signd;
127
128 if (rbo)
129 v = GUINT16_SWAP_LE_BE(v);
50842bdc 130 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
131 break;
132 }
133 case 32:
134 {
135 int32_t v = value.signd;
136
137 if (rbo)
138 v = GUINT32_SWAP_LE_BE(v);
50842bdc 139 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
140 break;
141 }
142 case 64:
143 {
144 int64_t v = value.signd;
145
146 if (rbo)
147 v = GUINT64_SWAP_LE_BE(v);
50842bdc 148 memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
dc3fffef
PP
149 break;
150 }
151 default:
0fbb9a9f 152 abort();
dc3fffef
PP
153 }
154 }
155
50842bdc 156 if (!bt_stream_pos_move(pos, size))
dc3fffef
PP
157 return -EFAULT;
158 return 0;
159}
160
161static
50842bdc 162int integer_write(struct bt_stream_pos *pos, union intval value,
c55a9f58 163 unsigned int alignment, unsigned int size, bt_bool is_signed,
50842bdc 164 enum bt_byte_order byte_order)
dc3fffef
PP
165{
166 if (!(alignment % CHAR_BIT)
167 && !(size % CHAR_BIT)) {
168 return aligned_integer_write(pos, value, alignment,
169 size, is_signed, byte_order);
170 }
171
50842bdc 172 if (!bt_stream_pos_align(pos, alignment))
dc3fffef
PP
173 return -EFAULT;
174
50842bdc 175 if (!bt_stream_pos_access_ok(pos, size))
dc3fffef
PP
176 return -EFAULT;
177
178 if (!is_signed) {
50842bdc 179 if (byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN)
dc3fffef
PP
180 bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
181 pos->mmap_base_offset, unsigned char,
182 pos->offset, size, value.unsignd);
183 else
184 bt_bitfield_write_be(mmap_align_addr(pos->base_mma) +
185 pos->mmap_base_offset, unsigned char,
186 pos->offset, size, value.unsignd);
187 } else {
50842bdc 188 if (byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN)
dc3fffef
PP
189 bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
190 pos->mmap_base_offset, unsigned char,
191 pos->offset, size, value.signd);
192 else
193 bt_bitfield_write_be(mmap_align_addr(pos->base_mma) +
194 pos->mmap_base_offset, unsigned char,
195 pos->offset, size, value.signd);
196 }
197
50842bdc 198 if (!bt_stream_pos_move(pos, size))
dc3fffef
PP
199 return -EFAULT;
200 return 0;
201}
202
203BT_HIDDEN
50842bdc
PP
204int bt_field_integer_write(struct bt_field_integer *int_field,
205 struct bt_stream_pos *pos,
206 enum bt_byte_order native_byte_order)
dc3fffef 207{
50842bdc
PP
208 struct bt_field_type *type = int_field->parent.type;
209 struct bt_field_type_integer *int_type = (void *) type;
210 enum bt_byte_order byte_order;
dc3fffef
PP
211 union intval value;
212
213 byte_order = int_type->user_byte_order;
50842bdc 214 if (byte_order == BT_BYTE_ORDER_NATIVE) {
dc3fffef
PP
215 byte_order = native_byte_order;
216 }
217
218 value.signd = int_field->payload.signd;
219 value.unsignd = int_field->payload.unsignd;
220 return integer_write(pos, value, type->alignment,
221 int_type->size, int_type->is_signed,
222 byte_order);
223}
224
225BT_HIDDEN
50842bdc
PP
226int bt_field_floating_point_write(
227 struct bt_field_floating_point *flt_field,
228 struct bt_stream_pos *pos,
229 enum bt_byte_order native_byte_order)
dc3fffef 230{
50842bdc
PP
231 struct bt_field_type *type = flt_field->parent.type;
232 struct bt_field_type_floating_point *flt_type = (void *) type;
233 enum bt_byte_order byte_order;
dc3fffef
PP
234 union intval value;
235 unsigned int size;
236
237 byte_order = flt_type->user_byte_order;
50842bdc 238 if (byte_order == BT_BYTE_ORDER_NATIVE) {
dc3fffef
PP
239 byte_order = native_byte_order;
240 }
241
242 if (flt_type->mant_dig == FLT_MANT_DIG) {
243 union u32f {
244 uint32_t u;
245 float f;
246 } u32f;
247
248 u32f.f = (float) flt_field->payload;
249 value.unsignd = u32f.u;
250 size = 32;
251 } else if (flt_type->mant_dig == DBL_MANT_DIG) {
252 union u64d {
253 uint64_t u;
254 double d;
255 } u64d;
256
257 u64d.d = flt_field->payload;
258 value.unsignd = u64d.u;
259 size = 64;
260 } else {
261 return -EINVAL;
262 }
263
c55a9f58 264 return integer_write(pos, value, type->alignment, size, BT_FALSE,
dc3fffef
PP
265 byte_order);
266}
267
268BT_HIDDEN
50842bdc 269void bt_stream_pos_packet_seek(struct bt_stream_pos *pos, size_t index,
dc3fffef
PP
270 int whence)
271{
272 int ret;
273
274 assert(whence == SEEK_CUR && index == 0);
275
276 if (pos->base_mma) {
277 /* unmap old base */
278 ret = munmap_align(pos->base_mma);
279 if (ret) {
0fbb9a9f
PP
280 // FIXME: this can legitimately fail?
281 abort();
dc3fffef
PP
282 }
283 pos->base_mma = NULL;
284 }
285
286 /* The writer will add padding */
287 pos->mmap_offset += pos->packet_size / CHAR_BIT;
108e5a1e 288 pos->packet_size = PACKET_LEN_INCREMENT;
dc3fffef
PP
289 do {
290 ret = bt_posix_fallocate(pos->fd, pos->mmap_offset,
291 pos->packet_size / CHAR_BIT);
292 } while (ret == EINTR);
293 assert(ret == 0);
294 pos->offset = 0;
295
296 /* map new base. Need mapping length from header. */
297 pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
298 pos->flags, pos->fd, pos->mmap_offset);
299 if (pos->base_mma == MAP_FAILED) {
0fbb9a9f
PP
300 // FIXME: this can legitimately fail?
301 abort();
dc3fffef
PP
302 }
303}
This page took 0.045411 seconds and 4 git commands to generate.