2 * Copyright 2016 Józef Kucia for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #ifndef __VKD3D_COMMON_H
20 #define __VKD3D_COMMON_H
23 #define WIN32_LEAN_AND_MEAN
25 #include "vkd3d_types.h"
39 # define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
42 #define DIV_ROUND_UP(a, b) ((a) % (b) == 0 ? (a) / (b) : (a) / (b) + 1)
44 #define STATIC_ASSERT(e) extern void __VKD3D_STATIC_ASSERT__(int [(e) ? 1 : -1])
46 #define MEMBER_SIZE(t, m) sizeof(((t *)0)->m)
48 #define VKD3D_MAKE_TAG(ch0, ch1, ch2, ch3) \
49 ((uint32_t)(ch0) | ((uint32_t)(ch1) << 8) \
50 | ((uint32_t)(ch2) << 16) | ((uint32_t)(ch3) << 24))
52 static inline size_t align(size_t addr
, size_t alignment
)
54 return (addr
+ (alignment
- 1)) & ~(alignment
- 1);
58 # define VKD3D_NORETURN __attribute__((noreturn))
59 # ifdef __MINGW_PRINTF_FORMAT
60 # define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args)))
62 # define VKD3D_PRINTF_FUNC(fmt, args) /* __attribute__((format(printf, fmt, args))) */
64 # define VKD3D_UNUSED __attribute__((unused))
65 # define VKD3D_UNREACHABLE __builtin_unreachable()
67 # define VKD3D_NORETURN
68 # define VKD3D_PRINTF_FUNC(fmt, args)
70 # define VKD3D_UNREACHABLE (void)0
73 VKD3D_NORETURN
static inline void vkd3d_unreachable_(const char *filename
, unsigned int line
)
75 fprintf(stderr
, "%s:%u: Aborting, reached unreachable code.\n", filename
, line
);
80 #define vkd3d_unreachable() VKD3D_UNREACHABLE
82 #define vkd3d_unreachable() vkd3d_unreachable_(__FILE__, __LINE__)
85 static inline unsigned int vkd3d_popcount(unsigned int v
)
89 #elif defined(__MINGW32__)
90 return __builtin_popcount(v
);
92 v
-= (v
>> 1) & 0x55555555;
93 v
= (v
& 0x33333333) + ((v
>> 2) & 0x33333333);
94 return (((v
+ (v
>> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
98 static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask
)
102 for (i
= 0, j
= 0; i
< sizeof(mask
) * CHAR_BIT
; ++i
)
104 if (mask
& (1u << i
))
110 return vkd3d_popcount(mask
) == j
;
113 /* Undefined for x == 0. */
114 static inline unsigned int vkd3d_log2i(unsigned int x
)
117 /* _BitScanReverse returns the index of the highest set bit,
118 * unlike clz which is 31 - index. */
120 _BitScanReverse(&result
, x
);
121 return (unsigned int)result
;
122 #elif defined(HAVE_BUILTIN_CLZ)
123 return __builtin_clz(x
) ^ 0x1f;
125 static const unsigned int l
[] =
127 ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
128 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
129 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
130 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
131 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
132 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
133 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
134 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
135 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
136 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
137 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
138 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
139 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
140 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
141 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
142 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
146 return (i
= x
>> 16) ? (x
= i
>> 8) ? l
[x
] + 24
147 : l
[i
] + 16 : (i
= x
>> 8) ? l
[i
] + 8 : l
[x
];
151 static inline void *vkd3d_memmem( const void *haystack
, size_t haystack_len
, const void *needle
, size_t needle_len
)
153 const char *str
= haystack
;
155 while (haystack_len
>= needle_len
)
157 if (!memcmp(str
, needle
, needle_len
))
165 static inline bool vkd3d_bound_range(size_t start
, size_t count
, size_t limit
)
167 #ifdef HAVE_BUILTIN_ADD_OVERFLOW
170 return !__builtin_add_overflow(start
, count
, &sum
) && sum
<= limit
;
172 return start
<= limit
&& count
<= limit
- start
;
176 static inline bool vkd3d_object_range_overflow(size_t start
, size_t count
, size_t size
)
178 return (~(size_t)0 - start
) / size
< count
;
181 static inline uint16_t vkd3d_make_u16(uint8_t low
, uint8_t high
)
183 return low
| ((uint16_t)high
<< 8);
186 static inline uint32_t vkd3d_make_u32(uint16_t low
, uint16_t high
)
188 return low
| ((uint32_t)high
<< 16);
191 static inline int vkd3d_u32_compare(uint32_t x
, uint32_t y
)
193 return (x
> y
) - (x
< y
);
196 static inline bool bitmap_clear(uint32_t *map
, unsigned int idx
)
198 return map
[idx
>> 5] &= ~(1u << (idx
& 0x1f));
201 static inline bool bitmap_set(uint32_t *map
, unsigned int idx
)
203 return map
[idx
>> 5] |= (1u << (idx
& 0x1f));
206 static inline bool bitmap_is_set(const uint32_t *map
, unsigned int idx
)
208 return map
[idx
>> 5] & (1u << (idx
& 0x1f));
211 static inline int ascii_isupper(int c
)
213 return 'A' <= c
&& c
<= 'Z';
216 static inline int ascii_tolower(int c
)
218 return ascii_isupper(c
) ? c
- 'A' + 'a' : c
;
221 static inline int ascii_strncasecmp(const char *a
, const char *b
, size_t n
)
227 c_a
= ascii_tolower(*a
++);
228 c_b
= ascii_tolower(*b
++);
229 if (c_a
!= c_b
|| !c_a
)
235 static inline int ascii_strcasecmp(const char *a
, const char *b
)
241 c_a
= ascii_tolower(*a
++);
242 c_b
= ascii_tolower(*b
++);
243 } while (c_a
== c_b
&& c_a
!= '\0');
249 # if HAVE_SYNC_ADD_AND_FETCH
250 static inline LONG
InterlockedIncrement(LONG
volatile *x
)
252 return __sync_add_and_fetch(x
, 1);
254 static inline LONG64
InterlockedIncrement64(LONG64
volatile *x
)
256 return __sync_add_and_fetch(x
, 1);
258 static inline LONG
InterlockedAdd(LONG
volatile *x
, LONG val
)
260 return __sync_add_and_fetch(x
, val
);
263 # error "InterlockedIncrement() not implemented for this platform"
264 # endif /* HAVE_SYNC_ADD_AND_FETCH */
266 # if HAVE_SYNC_SUB_AND_FETCH
267 static inline LONG
InterlockedDecrement(LONG
volatile *x
)
269 return __sync_sub_and_fetch(x
, 1);
272 # error "InterlockedDecrement() not implemented for this platform"
277 static inline void vkd3d_parse_version(const char *version
, int *major
, int *minor
)
279 *major
= atoi(version
);
281 while (isdigit(*version
))
286 *minor
= atoi(version
);
289 HRESULT
hresult_from_vkd3d_result(int vkd3d_result
);
292 static inline void *vkd3d_dlopen(const char *name
)
294 return LoadLibraryA(name
);
297 static inline void *vkd3d_dlsym(void *handle
, const char *symbol
)
299 return GetProcAddress(handle
, symbol
);
302 static inline int vkd3d_dlclose(void *handle
)
304 return FreeLibrary(handle
);
307 static inline const char *vkd3d_dlerror(void)
309 unsigned int error
= GetLastError();
310 static char message
[256];
312 if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error
, 0, message
, sizeof(message
), NULL
))
314 sprintf(message
, "Unknown error %u.\n", error
);
317 #elif defined(HAVE_DLFCN_H)
320 static inline void *vkd3d_dlopen(const char *name
)
322 return dlopen(name
, RTLD_NOW
);
325 static inline void *vkd3d_dlsym(void *handle
, const char *symbol
)
327 return dlsym(handle
, symbol
);
330 static inline int vkd3d_dlclose(void *handle
)
332 return dlclose(handle
);
335 static inline const char *vkd3d_dlerror(void)
340 static inline void *vkd3d_dlopen(const char *name
)
345 static inline void *vkd3d_dlsym(void *handle
, const char *symbol
)
350 static inline int vkd3d_dlclose(void *handle
)
355 static inline const char *vkd3d_dlerror(void)
357 return "Not implemented for this platform.\n";
361 #endif /* __VKD3D_COMMON_H */