1// Copyright (c) 2013 Austin T. Clements. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4
5#ifndef _ELFPP_COMMON_HH_
6#define _ELFPP_COMMON_HH_
7
8#define ELFPP_BEGIN_NAMESPACE namespace elf {
9#define ELFPP_END_NAMESPACE }
10#define ELFPP_BEGIN_INTERNAL namespace internal {
11#define ELFPP_END_INTERNAL }
12
13#include <cstdint>
14
15ELFPP_BEGIN_NAMESPACE
16
17/**
18 * A byte ordering.
19 */
20enum class byte_order
21{
22 native,
23 lsb,
24 msb
25};
26
27/**
28 * Return either byte_order::lsb or byte_order::msb. If the argument
29 * is byte_order::native, it will be resolved to whatever the native
30 * byte order is.
31 */
32static inline byte_order
33resolve_order(byte_order o)
34{
35 static const union
36 {
37 int i;
38 char c[sizeof(int)];
39 } test = {1};
40
41 if (o == byte_order::native)
42 return test.c[0] == 1 ? byte_order::lsb : byte_order::msb;
43 return o;
44}
45
46/**
47 * Return v converted from one byte order to another.
48 */
49template<typename T>
50T
51swizzle(T v, byte_order from, byte_order to)
52{
53 static_assert(sizeof(T) == 1 ||
54 sizeof(T) == 2 ||
55 sizeof(T) == 4 ||
56 sizeof(T) == 8,
57 "cannot swizzle type");
58
59 from = resolve_order(from);
60 to = resolve_order(to);
61
62 if (from == to)
63 return v;
64
65 switch (sizeof(T)) {
66 case 1:
67 return v;
68 case 2: {
69 std::uint16_t x = (std::uint16_t)v;
70 return (T)(((x&0xFF) << 8) | (x >> 8));
71 }
72 case 4:
73 return (T)__builtin_bswap32((std::uint32_t)v);
74 case 8:
75 return (T)__builtin_bswap64((std::uint64_t)v);
76 }
77}
78
79ELFPP_BEGIN_INTERNAL
80
81/**
82 * OrderPick selects between Native, LSB, and MSB based on ord.
83 */
84template<byte_order ord, typename Native, typename LSB, typename MSB>
85struct OrderPick;
86
87template<typename Native, typename LSB, typename MSB>
88struct OrderPick<byte_order::native, Native, LSB, MSB>
89{
90 typedef Native T;
91};
92
93template<typename Native, typename LSB, typename MSB>
94struct OrderPick<byte_order::lsb, Native, LSB, MSB>
95{
96 typedef LSB T;
97};
98
99template<typename Native, typename LSB, typename MSB>
100struct OrderPick<byte_order::msb, Native, LSB, MSB>
101{
102 typedef MSB T;
103};
104
105ELFPP_END_INTERNAL
106
107ELFPP_END_NAMESPACE
108
109#endif
110