1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
#ifndef bqtEndianHH
#define bqtEndianHH
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS /* for UINT16_C etc */
#endif
#include <stdint.h>
#if defined(__x86_64)||defined(__i386)
#define LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
#else
#undef LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
#endif
#ifdef WIN32
# define LL_FMT "I64"
#else
# define LL_FMT "ll"
#endif
static inline uint_fast16_t get_8(const void* p)
{
const unsigned char* data = (const unsigned char*)p;
return data[0];
}
static inline uint_fast16_t get_16(const void* p)
{
#ifdef LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
return *(const uint_least16_t*)p;
#else
const unsigned char* data = (const unsigned char*)p;
return get_8(data) | (get_8(data+1) << UINT16_C(8));
#endif
}
static inline uint_fast16_t R16r(const void* p)
{
#ifdef BIG_ENDIAN_AND_UNALIGNED_ACCESS_OK
return *(const uint_least16_t*)p;
#else
const unsigned char* data = (const unsigned char*)p;
return get_8(data+1) | (get_8(data) << UINT16_C(8));
#endif
}
static inline uint_fast32_t R24(const void* p)
{
/* Note: This might be faster if implemented through R32 and a bitwise and,
* but we cannot do that because we don't know if the third byte is a valid
* memory location.
*/
const unsigned char* data = (const unsigned char*)p;
return get_16(data) | (get_8(data+2) << UINT32_C(16));
}
static inline uint_fast32_t R24r(const void* p)
{
const unsigned char* data = (const unsigned char*)p;
return get_16(data+1) | (get_8(data) << UINT32_C(16));
}
static inline uint_fast32_t get_32(const void* p)
{
#ifdef LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
return *(const uint_least32_t*)p;
#else
const unsigned char* data = (const unsigned char*)p;
return get_16(data) | (get_16(data+2) << UINT32_C(16));
#endif
}
static inline uint_fast32_t R32r(const void* p)
{
#ifdef BIG_ENDIAN_AND_UNALIGNED_ACCESS_OK
return *(const uint_least32_t*)p;
#else
const unsigned char* data = (const unsigned char*)p;
return get_16(data+2) | (get_16(data) << UINT32_C(16));
#endif
}
#define L (uint_fast64_t)
static inline uint_fast64_t get_64(const void* p)
{
#ifdef LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
return *(const uint_least64_t*)p;
#else
const unsigned char* data = (const unsigned char*)p;
return (L get_32(data)) | ((L get_32(data+4)) << UINT64_C(32));
#endif
}
static inline uint_fast64_t R64r(const void* p)
{
#ifdef BIG_ENDIAN_AND_UNALIGNED_ACCESS_OK
return *(const uint_least64_t*)p;
#else
const unsigned char* data = (const unsigned char*)p;
return (L get_32(data+4)) | ((L get_32(data)) << UINT64_C(32));
#endif
}
#undef L
static inline uint_fast64_t get_n(const void* p, unsigned bytes)
{
const unsigned char* data = (const unsigned char*)p;
uint_fast64_t res(0);
switch(bytes)
{
case 8: return get_64(p);
case 4: return get_32(p);
case 2: return get_16(p);
case 7: res |= ((uint_fast64_t)get_8(data+6)) << 48;
case 6: res |= ((uint_fast64_t)get_8(data+5)) << 40;
case 5: res |= ((uint_fast64_t)get_16(data+3)) << 24;
case 3: res |= ((uint_fast64_t)get_16(data+1)) << 8;
case 1: res |= get_8(data);
}
return res;
}
static void put_8(void* p, uint_fast8_t value)
{
unsigned char* data = (unsigned char*)p;
data[0] = value;
}
static void put_16(void* p, uint_fast16_t value)
{
#ifdef LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
*(uint_least16_t*)p = value;
#else
unsigned char* data = (unsigned char*)p;
put_8(data+0, value );
put_8(data+1, value>>8);
#endif
}
static void W24(void* p, uint_fast32_t value)
{
unsigned char* data = (unsigned char*)p;
put_16(data+0, value);
put_8(data+2, value >> UINT32_C(16));
}
static void put_32(void* p, uint_fast32_t value)
{
#ifdef LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
*(uint_least32_t*)p = value;
#else
unsigned char* data = (unsigned char*)p;
put_16(data+0, value);
put_16(data+2, value >> UINT32_C(16));
#endif
}
static void put_64(void* p, uint_fast64_t value)
{
#ifdef LITTLE_ENDIAN_AND_UNALIGNED_ACCESS_OK
*(uint_least64_t*)p = value;
#else
unsigned char* data = (unsigned char*)p;
put_32(data+0, (value));
put_32(data+4, (value >> UINT64_C(32)));
#endif
}
static inline void put_n(void* p, uint_fast64_t value, unsigned bytes)
{
unsigned char* data = (unsigned char*)p;
switch(bytes)
{
case 8: put_64(p, value); break;
case 7: put_8(data+6, value>>48);
case 6: put_8(data+5, value>>40);
case 5: put_8(data+4, value>>32);
case 4: put_32(p, value); break;
case 3: W24(p, value); break;
case 2: put_16(p, value); break;
case 1: put_8(p, value); break;
}
}
#endif
|