28
28
#include <stdlib.h>
29
29
#include <inttypes.h>
30
30
31
+ #ifdef _WIN32
32
+ #include <intrin.h>
33
+ #include <malloc.h>
34
+ #else
35
+ #include <alloca.h>
36
+ #endif
37
+
31
38
/* set if CPU is big endian */
32
39
#undef WORDS_BIGENDIAN
33
40
41
+ #if defined(_MSC_VER )
42
+ #define likely (x ) (x)
43
+ #define unlikely (x ) (x)
44
+ #define force_inline __forceinline
45
+ #define no_inline __declspec(noinline)
46
+ #define __maybe_unused
47
+ #define __attribute__ (x )
48
+ #define __attribute (x )
49
+ #ifndef SSIZE_MAX
50
+ #define SSIZE_MAX INTPTR_MAX
51
+ typedef intptr_t ssize_t ;
52
+ #endif
53
+ #else
34
54
#define likely (x ) __builtin_expect(!!(x), 1)
35
55
#define unlikely (x ) __builtin_expect(!!(x), 0)
36
56
#define force_inline inline __attribute__((always_inline))
37
57
#define no_inline __attribute__((noinline))
38
58
#define __maybe_unused __attribute__((unused))
59
+ #endif
39
60
40
61
#define xglue (x , y ) x ## y
41
62
#define glue (x , y ) xglue(x, y)
@@ -114,27 +135,91 @@ static inline int64_t min_int64(int64_t a, int64_t b)
114
135
/* WARNING: undefined if a = 0 */
115
136
static inline int clz32 (unsigned int a )
116
137
{
138
+ #ifdef _MSC_VER
139
+ unsigned long idx ;
140
+ _BitScanReverse (& idx , a );
141
+ return 31 ^ idx ;
142
+ #else
117
143
return __builtin_clz (a );
144
+ #endif
118
145
}
119
146
120
147
/* WARNING: undefined if a = 0 */
121
148
static inline int clz64 (uint64_t a )
122
149
{
123
- return __builtin_clzll (a );
150
+ #ifdef _MSC_VER
151
+ unsigned long where ;
152
+ // BitScanReverse scans from MSB to LSB for first set bit.
153
+ // Returns 0 if no set bit is found.
154
+ #if INTPTR_MAX >= INT64_MAX // 64-bit
155
+ if (_BitScanReverse64 (& where , a ))
156
+ return (int )(63 - where );
157
+ #else
158
+ // Scan the high 32 bits.
159
+ if (_BitScanReverse (& where , (uint32_t )(a >> 32 )))
160
+ return (int )(63 - (where + 32 )); // Create a bit offset from the MSB.
161
+ // Scan the low 32 bits.
162
+ if (_BitScanReverse (& where , (uint32_t )(a )))
163
+ return (int )(63 - where );
164
+ #endif
165
+ return 64 ; // Undefined Behavior.
166
+ #else
167
+ return __builtin_clzll (a );
168
+ #endif
124
169
}
125
170
126
171
/* WARNING: undefined if a = 0 */
127
172
static inline int ctz32 (unsigned int a )
128
173
{
174
+ #ifdef _MSC_VER
175
+ unsigned long idx ;
176
+ _BitScanForward (& idx , a );
177
+ return idx ;
178
+ #else
129
179
return __builtin_ctz (a );
180
+ #endif
130
181
}
131
182
132
183
/* WARNING: undefined if a = 0 */
133
184
static inline int ctz64 (uint64_t a )
134
185
{
135
- return __builtin_ctzll (a );
186
+ #ifdef _MSC_VER
187
+ unsigned long where ;
188
+ // Search from LSB to MSB for first set bit.
189
+ // Returns zero if no set bit is found.
190
+ #if INTPTR_MAX >= INT64_MAX // 64-bit
191
+ if (_BitScanForward64 (& where , a ))
192
+ return (int )(where );
193
+ #else
194
+ // Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
195
+ // Scan the Low Word.
196
+ if (_BitScanForward (& where , (uint32_t )(a )))
197
+ return (int )(where );
198
+ // Scan the High Word.
199
+ if (_BitScanForward (& where , (uint32_t )(a >> 32 )))
200
+ return (int )(where + 32 ); // Create a bit offset from the LSB.
201
+ #endif
202
+ return 64 ;
203
+ #else
204
+ return __builtin_ctzll (a );
205
+ #endif
136
206
}
137
207
208
+ #ifdef _MSC_VER
209
+ #pragma pack(push, 1)
210
+ struct packed_u64 {
211
+ uint64_t v ;
212
+ };
213
+
214
+ struct packed_u32 {
215
+ uint32_t v ;
216
+ };
217
+
218
+ struct packed_u16 {
219
+ uint16_t v ;
220
+ };
221
+ #pragma pack(pop)
222
+ #else
138
223
struct __attribute__((packed )) packed_u64 {
139
224
uint64_t v ;
140
225
};
@@ -146,6 +231,7 @@ struct __attribute__((packed)) packed_u32 {
146
231
struct __attribute__((packed )) packed_u16 {
147
232
uint16_t v ;
148
233
};
234
+ #endif
149
235
150
236
static inline uint64_t get_u64 (const uint8_t * tab )
151
237
{
0 commit comments