// vim:fileencoding=utf-8:foldmethod=marker

#ifndef MISC_UTILS_H
#define MISC_UTILS_H

#include "../aliases/aliases.h"

#ifdef WP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WP_PLATFORM_CPP

#define KiB(SIZE) (((u64)SIZE) << 10)
#define MiB(SIZE) (((u64)SIZE) << 20)
#define GiB(SIZE) (((u64)SIZE) << 30)
#define TiB(SIZE) (((u64)SIZE) << 40)
#define PiB(SIZE) (((u64)SIZE) << 50)
#define EiB(SIZE) (((u64)SIZE) << 60)

#define KB(SIZE) (((u64)SIZE) * 1000llu)
#define MB(SIZE) (KB(SIZE)    * 1000llu)
#define GB(SIZE) (MB(SIZE)    * 1000llu)
#define TB(SIZE) (GB(SIZE)    * 1000llu)
#define PB(SIZE) (TB(SIZE)    * 1000llu)
#define EB(SIZE) (PB(SIZE)    * 1000llu)

#define wpMiscUtilsReservePadding(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]

#define U64_RSHIFT_OR_1(X)  (((u64)X) | (((u64)X) >> 1))
#define U64_RSHIFT_OR_2(X)  (((u64)X) | (((u64)X) >> 2))
#define U64_RSHIFT_OR_4(X)  (((u64)X) | (((u64)X) >> 4))
#define U64_RSHIFT_OR_8(X)  (((u64)X) | (((u64)X) >> 8))
#define U64_RSHIFT_OR_16(X)  (((u64)X) | (((u64)X) >> 16))
#define U64_RSHIFT_OR_32(X)  (((u64)X) | (((u64)X) >> 32))
#define wpMiscUtilsU64RoundUpPow2(X) (         \
	(                                            \
		U64_RSHIFT_OR_32(                          \
			U64_RSHIFT_OR_16(                        \
				U64_RSHIFT_OR_8(                       \
					U64_RSHIFT_OR_4(                     \
						U64_RSHIFT_OR_2(                   \
							U64_RSHIFT_OR_1(X - 1)           \
						)                                  \
					)                                    \
				)                                      \
			)                                        \
		)                                          \
	) + 1                                        \
)

#define wpMiscUtilsIsPowerOfTwo(NUM) ((NUM & (NUM - 1)) == 0)
#define wpMiscUtilsOffsetPointer(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET)))

#ifdef WP_PLATFORM_CPP
END_C_LINKAGE

#include <tuple>

#define wpMiscUtilsVaArgsCount(T, ...) (std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value)
#else
#define wpMiscUtilsVaArgsCount(T, ...) (sizeof((T[]){__VA_ARGS__})/sizeof(T))
#endif // !WP_PLATFORM_CPP

#endif // !MISC_UTILS_H
