Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

View File

@@ -0,0 +1,205 @@
/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */
#ifndef MPT_CRC_CRC_HPP
#define MPT_CRC_CRC_HPP
#include "mpt/base/array.hpp"
#include "mpt/base/detect.hpp"
#include "mpt/base/namespace.hpp"
#include "mpt/base/integer.hpp"
#include "mpt/base/memory.hpp"
#include <array>
#include <cstddef>
namespace mpt {
inline namespace MPT_INLINE_NS {
template <typename T, T polynomial, T initial, T resultXOR, bool reverseData>
class crc {
public:
using self_type = crc;
using value_type = T;
using byte_type = uint8;
static constexpr std::size_t size_bytes = sizeof(value_type);
static constexpr std::size_t size_bits = sizeof(value_type) * 8;
static constexpr value_type top_bit = static_cast<value_type>(1) << ((sizeof(value_type) * 8) - 1);
private:
template <typename Tint>
static constexpr Tint reverse(Tint value) noexcept {
const std::size_t bits = sizeof(Tint) * 8;
Tint result = 0;
for (std::size_t i = 0; i < bits; ++i) {
result <<= 1;
result |= static_cast<Tint>(value & 0x1);
value >>= 1;
}
return result;
}
static constexpr value_type calculate_table_entry(byte_type pos) noexcept {
value_type value = 0;
value = (static_cast<value_type>(reverseData ? reverse(pos) : pos) << (size_bits - 8));
for (std::size_t bit = 0; bit < 8; ++bit) {
if (value & top_bit) {
value = (value << 1) ^ polynomial;
} else {
value = (value << 1);
}
}
value = (reverseData ? reverse(value) : value);
return value;
}
private:
static constexpr std::array<value_type, 256> calculate_table() noexcept {
std::array<value_type, 256> t = mpt::init_array<value_type, 256>(value_type{});
for (std::size_t i = 0; i < 256; ++i) {
t[i] = calculate_table_entry(static_cast<byte_type>(i));
}
return t;
}
static constexpr std::array<value_type, 256> table = calculate_table();
private:
constexpr value_type read_table(byte_type pos) const noexcept {
return table[pos];
}
private:
value_type value;
public:
constexpr crc() noexcept
: value(initial) {
return;
}
constexpr void processByte(byte_type byte) noexcept {
if constexpr (reverseData) {
value = (value >> 8) ^ read_table(static_cast<byte_type>((value & 0xff) ^ byte));
} else {
value = (value << 8) ^ read_table(static_cast<byte_type>(((value >> (size_bits - 8)) & 0xff) ^ byte));
}
}
constexpr value_type result() const noexcept {
return (value ^ resultXOR);
}
public:
constexpr operator value_type() const noexcept {
return result();
}
inline crc & process(char c) noexcept {
processByte(mpt::byte_cast<byte_type>(c));
return *this;
}
inline crc & process(signed char c) noexcept {
processByte(static_cast<byte_type>(c));
return *this;
}
inline crc & process(unsigned char c) noexcept {
processByte(mpt::byte_cast<byte_type>(c));
return *this;
}
inline crc & process(std::byte c) noexcept {
processByte(mpt::byte_cast<byte_type>(c));
return *this;
}
template <typename InputIt>
inline crc & process(InputIt beg, InputIt end) {
for (InputIt it = beg; it != end; ++it) {
static_assert(sizeof(*it) == 1, "1 byte type required");
process(*it);
}
return *this;
}
template <typename Container>
inline crc & process(const Container & data) {
operator()(data.begin(), data.end());
return *this;
}
inline crc & operator()(char c) noexcept {
processByte(mpt::byte_cast<byte_type>(c));
return *this;
}
inline crc & operator()(signed char c) noexcept {
processByte(static_cast<byte_type>(c));
return *this;
}
inline crc & operator()(unsigned char c) noexcept {
processByte(mpt::byte_cast<byte_type>(c));
return *this;
}
inline crc & operator()(std::byte c) noexcept {
processByte(mpt::byte_cast<byte_type>(c));
return *this;
}
template <typename InputIt>
crc & operator()(InputIt beg, InputIt end) {
for (InputIt it = beg; it != end; ++it) {
static_assert(sizeof(*it) == 1, "1 byte type required");
operator()(*it);
}
return *this;
}
template <typename Container>
inline crc & operator()(const Container & data) {
operator()(data.begin(), data.end());
return *this;
}
template <typename InputIt>
crc(InputIt beg, InputIt end)
: value(initial) {
for (InputIt it = beg; it != end; ++it) {
static_assert(sizeof(*it) == 1, "1 byte type required");
process(*it);
}
}
template <typename Container>
inline crc(const Container & data)
: value(initial) {
process(data.begin(), data.end());
}
};
using crc16 = crc<uint16, 0x8005, 0, 0, true>;
using crc32 = crc<uint32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true>;
using crc32_ogg = crc<uint32, 0x04C11DB7, 0, 0, false>;
using crc32c = crc<uint32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true>;
using crc64_jones = crc<uint64, 0xAD93D23594C935A9ull, 0xFFFFFFFFFFFFFFFFull, 0, true>;
} // namespace MPT_INLINE_NS
} // namespace mpt
#endif // MPT_CRC_CRC_HPP

View File

@@ -0,0 +1,49 @@
/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */
#ifndef MPT_BASE_TESTS_CRC_HPP
#define MPT_BASE_TESTS_CRC_HPP
#include "mpt/base/detect_compiler.hpp"
#include "mpt/base/namespace.hpp"
#include "mpt/crc/crc.hpp"
#include "mpt/test/test.hpp"
#include "mpt/test/test_macros.hpp"
#include <string>
namespace mpt {
inline namespace MPT_INLINE_NS {
namespace tests {
namespace crc {
#if MPT_COMPILER_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#endif
MPT_TEST_GROUP_INLINE("mpt/crc")
#if MPT_COMPILER_CLANG
#pragma clang diagnostic pop
#endif
{
MPT_TEST_EXPECT_EQUAL(mpt::crc32(std::string("123456789")), 0xCBF43926u);
MPT_TEST_EXPECT_EQUAL(mpt::crc32_ogg(std::string("123456789")), 0x89a1897fu);
}
} // namespace crc
} // namespace tests
} // namespace MPT_INLINE_NS
} // namespace mpt
#endif // MPT_BASE_TESTS_CRC_HPP