#pragma once
#include <stdint.h>
#include <algorithm>
#include <atomic>
#include <chrono>
#include <cstring>
#include <limits>
namespace GDeflate
{
template<int N, typename T>
static inline T _align(T a)
{
return (a + T(N) - 1) & ~(T(N) - 1);
}
template<typename T>
static inline T _divRoundup(T a, T b)
{
return (a + b - 1) / b;
}
template<typename T>
static inline uint32_t _lzCount(T a)
{
uint32_t n = 0;
while (0 == (a & 1) && n < sizeof(T) * 8)
{
a >>= 1;
++n;
}
return n;
}
template<typename T>
static inline T GetBits(uint32_t*& in, uint32_t& offset, uint32_t numBitsToRead)
{
constexpr uint32_t kBitsPerBucket = sizeof(*in) * 8;
T bits = 0;
uint32_t numBitsConsumed = 0;
while (numBitsConsumed < numBitsToRead)
{
const uint32_t numBits =
std::min(numBitsToRead - numBitsConsumed, kBitsPerBucket - (offset % kBitsPerBucket));
const T mask = std::numeric_limits<T>().max() >> (sizeof(T) * 8 - numBits);
bits |= (T(*in >> (offset % kBitsPerBucket)) & mask) << numBitsConsumed;
offset += numBits;
numBitsConsumed += numBits;
if (0 == offset % kBitsPerBucket)
in++;
}
return bits;
}
}