mirror of
https://github.com/TomHarte/CLK.git
synced 2025-03-27 19:33:26 +00:00
Remove need for a CRC generator instance.
This commit is contained in:
parent
0310db5f24
commit
07493a6b18
@ -8,53 +8,36 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Sizes.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Numeric {
|
||||
namespace {
|
||||
|
||||
constexpr auto reverse_map = [] {
|
||||
std::array<uint8_t, 256> table{};
|
||||
for(std::size_t c = 0; c < 256; ++c) {
|
||||
table[c] = uint8_t(
|
||||
((c & 0x80) >> 7) |
|
||||
((c & 0x40) >> 5) |
|
||||
((c & 0x20) >> 3) |
|
||||
((c & 0x10) >> 1) |
|
||||
((c & 0x08) << 1) |
|
||||
((c & 0x04) << 3) |
|
||||
((c & 0x02) << 5) |
|
||||
((c & 0x01) << 7)
|
||||
);
|
||||
}
|
||||
return table;
|
||||
} ();
|
||||
|
||||
}
|
||||
|
||||
/// @returns @c source with the order of its bits reversed. E.g. if @c IntT is @c uint8_t then
|
||||
/// the reverse of bit pattern abcd efgh is hgfd dcba.
|
||||
template <typename IntT> constexpr IntT bit_reverse(IntT source);
|
||||
|
||||
// The single-byte specialisation uses a lookup table.
|
||||
template<> constexpr uint8_t bit_reverse<uint8_t>(const uint8_t source) {
|
||||
return reverse_map[source];
|
||||
template<> constexpr uint8_t bit_reverse<uint8_t>(uint8_t source) {
|
||||
source = uint8_t(((source & 0b1111'0000) >> 4) | ((source & 0b0000'1111) << 4));
|
||||
source = uint8_t(((source & 0b1100'1100) >> 2) | ((source & 0b0011'0011) << 2));
|
||||
source = uint8_t(((source & 0b1010'1010) >> 1) | ((source & 0b0101'0101) << 1));
|
||||
return source;
|
||||
}
|
||||
|
||||
// All other versions recursively subdivide.
|
||||
template <typename IntT>
|
||||
constexpr IntT bit_reverse(const IntT source) {
|
||||
static_assert(std::is_same_v<IntT, uint16_t> || std::is_same_v<IntT, uint32_t> || std::is_same_v<IntT, uint64_t>);
|
||||
using HalfIntT =
|
||||
std::conditional_t<std::is_same_v<IntT, uint16_t>, uint8_t,
|
||||
std::conditional_t<std::is_same_v<IntT, uint32_t>, uint16_t,
|
||||
uint32_t>>;
|
||||
constexpr auto HalfShift = sizeof(IntT) * 4;
|
||||
|
||||
constexpr auto HalfSize = sizeof(IntT) * 4;
|
||||
using HalfIntT = uint_t<HalfSize>;
|
||||
|
||||
return IntT(
|
||||
IntT(bit_reverse(HalfIntT(source))) << HalfShift) |
|
||||
IntT(bit_reverse(HalfIntT(source >> HalfShift))
|
||||
IntT(bit_reverse(HalfIntT(source >> HalfSize))) |
|
||||
IntT(bit_reverse(HalfIntT(source))) << HalfSize
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Numeric {
|
||||
|
||||
/// @returns The bits of @c input with a 0 bit inserted between each and
|
||||
|
@ -71,30 +71,24 @@ public:
|
||||
void set_value(const IntType value) { value_ = value; }
|
||||
|
||||
/*!
|
||||
A compound for:
|
||||
|
||||
reset()
|
||||
[add all data from @c data]
|
||||
get_value()
|
||||
Calculates the CRC of the provided collection, assuming that it contains `uint8_t`s.
|
||||
*/
|
||||
template <typename Collection> IntType compute_crc(const Collection &data) {
|
||||
return compute_crc(data.begin(), data.end());
|
||||
template <typename Collection>
|
||||
static IntType crc_of(const Collection &data) {
|
||||
return crc_of(data.begin(), data.end());
|
||||
}
|
||||
|
||||
/*!
|
||||
A compound for:
|
||||
|
||||
reset()
|
||||
[add all data from @c begin to @c end]
|
||||
get_value()
|
||||
Calculates the CRC of all `uint8_t`s in the range defined by @c begin and @c end.
|
||||
*/
|
||||
template <typename Iterator> IntType compute_crc(Iterator begin, const Iterator end) {
|
||||
reset();
|
||||
template <typename Iterator>
|
||||
static IntType crc_of(Iterator begin, const Iterator end) {
|
||||
Generator generator;
|
||||
while(begin != end) {
|
||||
add(*begin);
|
||||
generator.add(*begin);
|
||||
++begin;
|
||||
}
|
||||
return get_value();
|
||||
return generator.get_value();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -8,9 +8,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
template <int size> struct uint_t_impl;
|
||||
template <> struct uint_t_impl<8> { using type = uint8_t; };
|
||||
template <> struct uint_t_impl<16> { using type = uint16_t; };
|
||||
template <> struct uint_t_impl<32> { using type = uint32_t; };
|
||||
template <> struct uint_t_impl<64> { using type = uint64_t; };
|
||||
|
||||
/// Unsigned integer types templated on size; `uint_t<8> = uint8_t`; `uint_t<16> = uint16_t`, etc.
|
||||
template <int size> using uint_t = typename uint_t_impl<size>::type;
|
||||
|
||||
/*!
|
||||
Maps to the smallest integral type that can contain max_value, from the following options:
|
||||
|
||||
|
@ -15,26 +15,22 @@
|
||||
|
||||
@implementation CRCTests
|
||||
|
||||
- (uint16_t)crcOfData:(uint8_t *)data length:(size_t)length generator:(CRC::CCITT &)generator {
|
||||
generator.reset();
|
||||
for(size_t c = 0; c < length; c++)
|
||||
generator.add(data[c]);
|
||||
return generator.get_value();
|
||||
- (uint16_t)crcOfData:(const uint8_t *)data length:(size_t)length generator:(CRC::CCITT &)generator {
|
||||
return generator.crc_of(data, data+length);
|
||||
}
|
||||
|
||||
- (void)testIDMark {
|
||||
uint8_t IDMark[] = {
|
||||
constexpr uint8_t IDMark[] = {
|
||||
0xa1, 0xa1, 0xa1, 0xfe, 0x00, 0x00, 0x01, 0x01
|
||||
};
|
||||
uint16_t crc = 0xfa0c;
|
||||
CRC::CCITT crcGenerator;
|
||||
constexpr uint16_t crc = 0xfa0c;
|
||||
const uint16_t computedCRC = CRC::CCITT::crc_of(std::begin(IDMark), std::end(IDMark));
|
||||
|
||||
uint16_t computedCRC = [self crcOfData:IDMark length:sizeof(IDMark) generator:crcGenerator];
|
||||
XCTAssert(computedCRC == crc, @"Calculated CRC should have been %04x, was %04x", crc, computedCRC);
|
||||
}
|
||||
|
||||
- (void)testData {
|
||||
uint8_t sectorData[] = {
|
||||
constexpr uint8_t sectorData[] = {
|
||||
0xa1, 0xa1, 0xa1, 0xfb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x53, 0x45, 0x44, 0x4f,
|
||||
0x52, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
@ -53,27 +49,20 @@
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20
|
||||
};
|
||||
uint16_t crc = 0x4de7;
|
||||
CRC::CCITT crcGenerator;
|
||||
constexpr uint16_t crc = 0x4de7;
|
||||
uint16_t computedCRC = CRC::CCITT::crc_of(std::begin(sectorData), std::end(sectorData));
|
||||
|
||||
uint16_t computedCRC = [self crcOfData:sectorData length:sizeof(sectorData) generator:crcGenerator];
|
||||
XCTAssert(computedCRC == crc, @"Calculated CRC should have been %04x, was %04x", crc, computedCRC);
|
||||
}
|
||||
|
||||
- (void)testCCITTCheck {
|
||||
CRC::CCITT crcGenerator;
|
||||
for(auto c: std::string("123456789")) {
|
||||
crcGenerator.add(c);
|
||||
}
|
||||
XCTAssertEqual(crcGenerator.get_value(), 0x29b1);
|
||||
constexpr char testString[] = "123456789";
|
||||
XCTAssertEqual(CRC::CCITT::crc_of(std::begin(testString), std::end(testString) - 1), 0x29b1);
|
||||
}
|
||||
|
||||
- (void)testCRC32Check {
|
||||
CRC::CRC32 crcGenerator;
|
||||
for(auto c: std::string("123456789")) {
|
||||
crcGenerator.add(c);
|
||||
}
|
||||
XCTAssertEqual(crcGenerator.get_value(), 0xcbf43926);
|
||||
constexpr char testString[] = "123456789";
|
||||
XCTAssertEqual(CRC::CRC32::crc_of(std::begin(testString), std::end(testString) - 1), 0xcbf43926);
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -47,7 +47,7 @@ WOZ::WOZ(const std::string &file_name) :
|
||||
post_crc_contents_ = file_.read(size_t(file_.stats().st_size - 12));
|
||||
|
||||
// Test the CRC.
|
||||
const uint32_t computed_crc = crc_generator.compute_crc(post_crc_contents_);
|
||||
const uint32_t computed_crc = CRC::CRC32::crc_of(post_crc_contents_);
|
||||
if(crc != computed_crc) {
|
||||
throw Error::InvalidFormat;
|
||||
}
|
||||
@ -209,7 +209,7 @@ void WOZ::set_tracks(const std::map<Track::Address, std::unique_ptr<Track>> &tra
|
||||
}
|
||||
|
||||
// Calculate the new CRC.
|
||||
const uint32_t crc = crc_generator.compute_crc(post_crc_contents_);
|
||||
const uint32_t crc = CRC::CRC32::crc_of(post_crc_contents_);
|
||||
|
||||
// Grab the file lock, then write the CRC, then just dump the entire file buffer.
|
||||
std::lock_guard lock_guard(file_.get_file_access_mutex());
|
||||
|
@ -42,7 +42,6 @@ private:
|
||||
long tracks_offset_ = -1;
|
||||
|
||||
std::vector<uint8_t> post_crc_contents_;
|
||||
CRC::CRC32 crc_generator;
|
||||
|
||||
/*!
|
||||
Gets the in-file offset of a track.
|
||||
|
Loading…
x
Reference in New Issue
Block a user