lib: remove CV snapshot property from stream beginning/end message
[babeltrace.git] / include / babeltrace / bitfield-internal.h
CommitLineData
d79865b9
MD
1#ifndef _BABELTRACE_BITFIELD_H
2#define _BABELTRACE_BITFIELD_H
6dc2ca62
MD
3
4/*
6dc2ca62
MD
5 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
c462e188
MD
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
6dc2ca62
MD
24 */
25
26#include <stdint.h> /* C99 5.2.4.2 Numerical limits */
3d9990ac 27#include <babeltrace/compat/limits-internal.h> /* C99 5.2.4.2 Numerical limits */
3d9990ac 28#include <babeltrace/endian-internal.h> /* Non-standard BIG_ENDIAN, LITTLE_ENDIAN, BYTE_ORDER */
6dc2ca62 29
08228826 30/* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
5f61bf21 31#define _bt_piecewise_rshift(_v, _shift) \
6dc2ca62 32({ \
5f61bf21
MD
33 typeof(_v) ___v = (_v); \
34 typeof(_shift) ___shift = (_shift); \
35 unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \
36 unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \
6dc2ca62
MD
37 \
38 for (; sb; sb--) \
5f61bf21
MD
39 ___v >>= sizeof(___v) * CHAR_BIT - 1; \
40 ___v >>= final; \
6dc2ca62
MD
41})
42
5f61bf21 43#define _bt_piecewise_lshift(_v, _shift) \
08228826 44({ \
5f61bf21
MD
45 typeof(_v) ___v = (_v); \
46 typeof(_shift) ___shift = (_shift); \
47 unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \
48 unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \
08228826
MD
49 \
50 for (; sb; sb--) \
5f61bf21
MD
51 ___v <<= sizeof(___v) * CHAR_BIT - 1; \
52 ___v <<= final; \
08228826
MD
53})
54
cca767be 55#define _bt_is_signed_type(type) ((type) -1 < (type) 0)
08228826 56
a2d16120
PP
57/*
58 * NOTE: The cast to (uint64_t) below ensures that we're not casting a
59 * negative value, which is undefined in C. However, this limits the
60 * maximum type size of `type` and `v` to 64-bit. The
61 * _bt_check_max_64bit() is used to check that the users of this header
62 * do not use types with a size greater than 64-bit.
63 */
d79865b9 64#define _bt_unsigned_cast(type, v) \
08228826
MD
65({ \
66 (sizeof(v) < sizeof(type)) ? \
a2d16120 67 ((type) (v)) & ((type) (~(~(uint64_t) 0 << (sizeof(v) * CHAR_BIT)))) : \
08228826
MD
68 (type) (v); \
69})
70
a2d16120
PP
71#define _bt_check_max_64bit(type) \
72 char _max_64bit_assertion[sizeof(type) <= sizeof(uint64_t) ? 1 : -1] __attribute__((unused))
73
6dc2ca62 74/*
d79865b9 75 * bt_bitfield_write - write integer to a bitfield in native endianness
6dc2ca62
MD
76 *
77 * Save integer to the bitfield, which starts at the "start" bit, has "len"
78 * bits.
79 * The inside of a bitfield is from high bits to low bits.
80 * Uses native endianness.
81 * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
82 * For signed "v", sign-extend v if bitfield is larger than v.
83 *
84 * On little endian, bytes are placed from the less significant to the most
85 * significant. Also, consecutive bitfields are placed from lower bits to higher
86 * bits.
87 *
88 * On big endian, bytes are places from most significant to less significant.
89 * Also, consecutive bitfields are placed from higher to lower bits.
90 */
91
5f61bf21 92#define _bt_bitfield_write_le(_ptr, type, _start, _length, _v) \
6dc2ca62 93do { \
5f61bf21 94 typeof(_v) __v = (_v); \
9128428b 95 type *__ptr = (void *) (_ptr); \
5f61bf21 96 unsigned long __start = (_start), __length = (_length); \
47e0f2e2
MD
97 type mask, cmask; \
98 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
6dc2ca62
MD
99 unsigned long start_unit, end_unit, this_unit; \
100 unsigned long end, cshift; /* cshift is "complement shift" */ \
6dc2ca62 101 \
5f61bf21 102 if (!__length) \
6dc2ca62
MD
103 break; \
104 \
5f61bf21
MD
105 end = __start + __length; \
106 start_unit = __start / ts; \
6dc2ca62
MD
107 end_unit = (end + (ts - 1)) / ts; \
108 \
109 /* Trim v high bits */ \
5f61bf21
MD
110 if (__length < sizeof(__v) * CHAR_BIT) \
111 __v &= ~((~(typeof(__v)) 0) << __length); \
6dc2ca62
MD
112 \
113 /* We can now append v with a simple "or", shift it piece-wise */ \
114 this_unit = start_unit; \
115 if (start_unit == end_unit - 1) { \
5f61bf21 116 mask = ~((~(type) 0) << (__start % ts)); \
6dc2ca62 117 if (end % ts) \
47e0f2e2 118 mask |= (~(type) 0) << (end % ts); \
5f61bf21 119 cmask = (type) __v << (__start % ts); \
08228826 120 cmask &= ~mask; \
5f61bf21
MD
121 __ptr[this_unit] &= mask; \
122 __ptr[this_unit] |= cmask; \
6dc2ca62
MD
123 break; \
124 } \
5f61bf21
MD
125 if (__start % ts) { \
126 cshift = __start % ts; \
47e0f2e2 127 mask = ~((~(type) 0) << cshift); \
5f61bf21 128 cmask = (type) __v << cshift; \
08228826 129 cmask &= ~mask; \
5f61bf21
MD
130 __ptr[this_unit] &= mask; \
131 __ptr[this_unit] |= cmask; \
132 __v = _bt_piecewise_rshift(__v, ts - cshift); \
133 __start += ts - cshift; \
6dc2ca62
MD
134 this_unit++; \
135 } \
136 for (; this_unit < end_unit - 1; this_unit++) { \
5f61bf21
MD
137 __ptr[this_unit] = (type) __v; \
138 __v = _bt_piecewise_rshift(__v, ts); \
139 __start += ts; \
6dc2ca62
MD
140 } \
141 if (end % ts) { \
47e0f2e2 142 mask = (~(type) 0) << (end % ts); \
5f61bf21 143 cmask = (type) __v; \
08228826 144 cmask &= ~mask; \
5f61bf21
MD
145 __ptr[this_unit] &= mask; \
146 __ptr[this_unit] |= cmask; \
6dc2ca62 147 } else \
5f61bf21 148 __ptr[this_unit] = (type) __v; \
6dc2ca62
MD
149} while (0)
150
5f61bf21 151#define _bt_bitfield_write_be(_ptr, type, _start, _length, _v) \
6dc2ca62 152do { \
5f61bf21 153 typeof(_v) __v = (_v); \
9128428b 154 type *__ptr = (void *) (_ptr); \
5f61bf21 155 unsigned long __start = (_start), __length = (_length); \
47e0f2e2
MD
156 type mask, cmask; \
157 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
6dc2ca62
MD
158 unsigned long start_unit, end_unit, this_unit; \
159 unsigned long end, cshift; /* cshift is "complement shift" */ \
6dc2ca62 160 \
5f61bf21 161 if (!__length) \
6dc2ca62
MD
162 break; \
163 \
5f61bf21
MD
164 end = __start + __length; \
165 start_unit = __start / ts; \
6dc2ca62
MD
166 end_unit = (end + (ts - 1)) / ts; \
167 \
168 /* Trim v high bits */ \
5f61bf21
MD
169 if (__length < sizeof(__v) * CHAR_BIT) \
170 __v &= ~((~(typeof(__v)) 0) << __length); \
6dc2ca62
MD
171 \
172 /* We can now append v with a simple "or", shift it piece-wise */ \
173 this_unit = end_unit - 1; \
174 if (start_unit == end_unit - 1) { \
47e0f2e2 175 mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \
5f61bf21
MD
176 if (__start % ts) \
177 mask |= (~((type) 0)) << (ts - (__start % ts)); \
178 cmask = (type) __v << ((ts - (end % ts)) % ts); \
08228826 179 cmask &= ~mask; \
5f61bf21
MD
180 __ptr[this_unit] &= mask; \
181 __ptr[this_unit] |= cmask; \
6dc2ca62
MD
182 break; \
183 } \
184 if (end % ts) { \
185 cshift = end % ts; \
47e0f2e2 186 mask = ~((~(type) 0) << (ts - cshift)); \
5f61bf21 187 cmask = (type) __v << (ts - cshift); \
08228826 188 cmask &= ~mask; \
5f61bf21
MD
189 __ptr[this_unit] &= mask; \
190 __ptr[this_unit] |= cmask; \
191 __v = _bt_piecewise_rshift(__v, cshift); \
6dc2ca62
MD
192 end -= cshift; \
193 this_unit--; \
194 } \
08228826 195 for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
5f61bf21
MD
196 __ptr[this_unit] = (type) __v; \
197 __v = _bt_piecewise_rshift(__v, ts); \
6dc2ca62
MD
198 end -= ts; \
199 } \
5f61bf21
MD
200 if (__start % ts) { \
201 mask = (~(type) 0) << (ts - (__start % ts)); \
202 cmask = (type) __v; \
08228826 203 cmask &= ~mask; \
5f61bf21
MD
204 __ptr[this_unit] &= mask; \
205 __ptr[this_unit] |= cmask; \
6dc2ca62 206 } else \
5f61bf21 207 __ptr[this_unit] = (type) __v; \
6dc2ca62
MD
208} while (0)
209
210/*
d79865b9
MD
211 * bt_bitfield_write - write integer to a bitfield in native endianness
212 * bt_bitfield_write_le - write integer to a bitfield in little endian
213 * bt_bitfield_write_be - write integer to a bitfield in big endian
6dc2ca62
MD
214 */
215
216#if (BYTE_ORDER == LITTLE_ENDIAN)
217
47e0f2e2
MD
218#define bt_bitfield_write(ptr, type, _start, _length, _v) \
219 _bt_bitfield_write_le(ptr, type, _start, _length, _v)
6dc2ca62 220
47e0f2e2
MD
221#define bt_bitfield_write_le(ptr, type, _start, _length, _v) \
222 _bt_bitfield_write_le(ptr, type, _start, _length, _v)
a2d16120 223
47e0f2e2
MD
224#define bt_bitfield_write_be(ptr, type, _start, _length, _v) \
225 _bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v)
6dc2ca62
MD
226
227#elif (BYTE_ORDER == BIG_ENDIAN)
228
47e0f2e2
MD
229#define bt_bitfield_write(ptr, type, _start, _length, _v) \
230 _bt_bitfield_write_be(ptr, type, _start, _length, _v)
6dc2ca62 231
47e0f2e2
MD
232#define bt_bitfield_write_le(ptr, type, _start, _length, _v) \
233 _bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v)
a2d16120 234
47e0f2e2
MD
235#define bt_bitfield_write_be(ptr, type, _start, _length, _v) \
236 _bt_bitfield_write_be(ptr, type, _start, _length, _v)
6dc2ca62
MD
237
238#else /* (BYTE_ORDER == PDP_ENDIAN) */
239
240#error "Byte order not supported"
241
242#endif
243
5f61bf21 244#define _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \
6dc2ca62 245do { \
5f61bf21 246 typeof(*(_vptr)) *__vptr = (_vptr); \
5f61bf21 247 typeof(*__vptr) __v; \
9128428b 248 type *__ptr = (void *) (_ptr); \
5f61bf21 249 unsigned long __start = (_start), __length = (_length); \
47e0f2e2
MD
250 type mask, cmask; \
251 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
6dc2ca62
MD
252 unsigned long start_unit, end_unit, this_unit; \
253 unsigned long end, cshift; /* cshift is "complement shift" */ \
08228826 254 \
a2d16120
PP
255 { _bt_check_max_64bit(type); } \
256 { _bt_check_max_64bit(typeof(*_vptr)); } \
257 { _bt_check_max_64bit(typeof(*_ptr)); } \
258 \
5f61bf21
MD
259 if (!__length) { \
260 *__vptr = 0; \
08228826
MD
261 break; \
262 } \
263 \
5f61bf21
MD
264 end = __start + __length; \
265 start_unit = __start / ts; \
08228826 266 end_unit = (end + (ts - 1)) / ts; \
6a7b3345
MD
267 \
268 this_unit = end_unit - 1; \
5f61bf21
MD
269 if (_bt_is_signed_type(typeof(__v)) \
270 && (__ptr[this_unit] & ((type) 1 << ((end % ts ? : ts) - 1)))) \
271 __v = ~(typeof(__v)) 0; \
6a7b3345 272 else \
5f61bf21 273 __v = 0; \
6a7b3345 274 if (start_unit == end_unit - 1) { \
5f61bf21
MD
275 cmask = __ptr[this_unit]; \
276 cmask >>= (__start % ts); \
277 if ((end - __start) % ts) { \
278 mask = ~((~(type) 0) << (end - __start)); \
6a7b3345
MD
279 cmask &= mask; \
280 } \
5f61bf21
MD
281 __v = _bt_piecewise_lshift(__v, end - __start); \
282 __v |= _bt_unsigned_cast(typeof(__v), cmask); \
283 *__vptr = __v; \
6a7b3345
MD
284 break; \
285 } \
286 if (end % ts) { \
287 cshift = end % ts; \
47e0f2e2 288 mask = ~((~(type) 0) << cshift); \
5f61bf21 289 cmask = __ptr[this_unit]; \
6a7b3345 290 cmask &= mask; \
5f61bf21
MD
291 __v = _bt_piecewise_lshift(__v, cshift); \
292 __v |= _bt_unsigned_cast(typeof(__v), cmask); \
6a7b3345
MD
293 end -= cshift; \
294 this_unit--; \
295 } \
08228826 296 for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
5f61bf21
MD
297 __v = _bt_piecewise_lshift(__v, ts); \
298 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
6a7b3345
MD
299 end -= ts; \
300 } \
5f61bf21
MD
301 if (__start % ts) { \
302 mask = ~((~(type) 0) << (ts - (__start % ts))); \
303 cmask = __ptr[this_unit]; \
304 cmask >>= (__start % ts); \
6a7b3345 305 cmask &= mask; \
5f61bf21
MD
306 __v = _bt_piecewise_lshift(__v, ts - (__start % ts)); \
307 __v |= _bt_unsigned_cast(typeof(__v), cmask); \
6a7b3345 308 } else { \
5f61bf21
MD
309 __v = _bt_piecewise_lshift(__v, ts); \
310 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
6a7b3345 311 } \
5f61bf21 312 *__vptr = __v; \
08228826
MD
313} while (0)
314
5f61bf21 315#define _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \
08228826 316do { \
5f61bf21 317 typeof(*(_vptr)) *__vptr = (_vptr); \
5f61bf21 318 typeof(*__vptr) __v; \
9128428b 319 type *__ptr = (void *) (_ptr); \
5f61bf21 320 unsigned long __start = (_start), __length = (_length); \
47e0f2e2
MD
321 type mask, cmask; \
322 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
08228826
MD
323 unsigned long start_unit, end_unit, this_unit; \
324 unsigned long end, cshift; /* cshift is "complement shift" */ \
6dc2ca62 325 \
a2d16120
PP
326 { _bt_check_max_64bit(type); } \
327 { _bt_check_max_64bit(typeof(*_vptr)); } \
328 { _bt_check_max_64bit(typeof(*_ptr)); } \
329 \
5f61bf21
MD
330 if (!__length) { \
331 *__vptr = 0; \
6dc2ca62 332 break; \
08228826 333 } \
6dc2ca62 334 \
5f61bf21
MD
335 end = __start + __length; \
336 start_unit = __start / ts; \
6dc2ca62 337 end_unit = (end + (ts - 1)) / ts; \
6a7b3345 338 \
08228826 339 this_unit = start_unit; \
5f61bf21
MD
340 if (_bt_is_signed_type(typeof(__v)) \
341 && (__ptr[this_unit] & ((type) 1 << (ts - (__start % ts) - 1)))) \
342 __v = ~(typeof(__v)) 0; \
6a7b3345 343 else \
5f61bf21 344 __v = 0; \
6a7b3345 345 if (start_unit == end_unit - 1) { \
5f61bf21 346 cmask = __ptr[this_unit]; \
6a7b3345 347 cmask >>= (ts - (end % ts)) % ts; \
5f61bf21
MD
348 if ((end - __start) % ts) { \
349 mask = ~((~(type) 0) << (end - __start)); \
6a7b3345
MD
350 cmask &= mask; \
351 } \
5f61bf21
MD
352 __v = _bt_piecewise_lshift(__v, end - __start); \
353 __v |= _bt_unsigned_cast(typeof(__v), cmask); \
354 *__vptr = __v; \
6a7b3345
MD
355 break; \
356 } \
5f61bf21
MD
357 if (__start % ts) { \
358 cshift = __start % ts; \
47e0f2e2 359 mask = ~((~(type) 0) << (ts - cshift)); \
5f61bf21 360 cmask = __ptr[this_unit]; \
6a7b3345 361 cmask &= mask; \
5f61bf21
MD
362 __v = _bt_piecewise_lshift(__v, ts - cshift); \
363 __v |= _bt_unsigned_cast(typeof(__v), cmask); \
364 __start += ts - cshift; \
6a7b3345
MD
365 this_unit++; \
366 } \
367 for (; this_unit < end_unit - 1; this_unit++) { \
5f61bf21
MD
368 __v = _bt_piecewise_lshift(__v, ts); \
369 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
370 __start += ts; \
6a7b3345
MD
371 } \
372 if (end % ts) { \
47e0f2e2 373 mask = ~((~(type) 0) << (end % ts)); \
5f61bf21 374 cmask = __ptr[this_unit]; \
6a7b3345
MD
375 cmask >>= ts - (end % ts); \
376 cmask &= mask; \
5f61bf21
MD
377 __v = _bt_piecewise_lshift(__v, end % ts); \
378 __v |= _bt_unsigned_cast(typeof(__v), cmask); \
6a7b3345 379 } else { \
5f61bf21
MD
380 __v = _bt_piecewise_lshift(__v, ts); \
381 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
6a7b3345 382 } \
5f61bf21 383 *__vptr = __v; \
6dc2ca62
MD
384} while (0)
385
6dc2ca62 386/*
d79865b9
MD
387 * bt_bitfield_read - read integer from a bitfield in native endianness
388 * bt_bitfield_read_le - read integer from a bitfield in little endian
389 * bt_bitfield_read_be - read integer from a bitfield in big endian
6dc2ca62
MD
390 */
391
08228826
MD
392#if (BYTE_ORDER == LITTLE_ENDIAN)
393
5f61bf21
MD
394#define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \
395 _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)
08228826 396
5f61bf21
MD
397#define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \
398 _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)
a2d16120 399
5f61bf21
MD
400#define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \
401 _bt_bitfield_read_be(_ptr, unsigned char, _start, _length, _vptr)
08228826
MD
402
403#elif (BYTE_ORDER == BIG_ENDIAN)
404
5f61bf21
MD
405#define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \
406 _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)
08228826 407
5f61bf21
MD
408#define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \
409 _bt_bitfield_read_le(_ptr, unsigned char, _start, _length, _vptr)
a2d16120 410
5f61bf21
MD
411#define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \
412 _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)
08228826
MD
413
414#else /* (BYTE_ORDER == PDP_ENDIAN) */
415
416#error "Byte order not supported"
417
418#endif
6dc2ca62 419
d79865b9 420#endif /* _BABELTRACE_BITFIELD_H */
This page took 0.073803 seconds and 4 git commands to generate.