Skip to content

Commit a8e4376

Browse files
util: Add crc64 module
1 parent f9ea5bf commit a8e4376

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

api/util/crc64.hpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// This file is a part of the IncludeOS unikernel - www.includeos.org
2+
//
3+
// Copyright 2017 Oslo and Akershus University College of Applied Sciences
4+
// and Alfred Bratterud
5+
//
6+
// Licensed under the Apache License, Version 2.0 the "License";
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
#pragma once
19+
#ifndef UTIL_CRC64_HPP
20+
#define UTIL_CRC64_HPP
21+
22+
#include <array>
23+
#include <cstdint>
24+
#include <string>
25+
#include <vector>
26+
27+
namespace util {
28+
29+
template<uint64_t POLY>
30+
struct crc64 {
31+
explicit crc64(const std::string& data) noexcept
32+
: crc64(data.data(), data.size())
33+
{}
34+
35+
explicit crc64(const std::vector<char>& data) noexcept
36+
: crc64(data.data(), data.size())
37+
{}
38+
39+
template<size_t N>
40+
explicit crc64(const std::array<char, N>& data) noexcept
41+
: crc64(data.data(), data.size())
42+
{}
43+
44+
constexpr explicit crc64(const char* data, size_t data_len) noexcept {
45+
crc_register_ = checksum(0, data, data_len);
46+
}
47+
48+
49+
static constexpr inline uint64_t checksum(uint64_t crc_accumulator, const char* data, size_t data_len) noexcept {
50+
auto crc64_table = get_table();
51+
52+
crc_accumulator = ~crc_accumulator;
53+
54+
while (data_len > 8) {
55+
crc_accumulator ^= static_cast<uint64_t>(data[0]) | static_cast<uint64_t>(data[1]) << 8 |
56+
static_cast<uint64_t>(data[2]) << 16 | static_cast<uint64_t>(data[3]) << 24 |
57+
static_cast<uint64_t>(data[4]) << 32 | static_cast<uint64_t>(data[5]) << 40 |
58+
static_cast<uint64_t>(data[6]) << 48 | static_cast<uint64_t>(data[7]) << 56;
59+
60+
crc_accumulator = crc64_table[7][crc_accumulator & 0xff] ^
61+
crc64_table[6][(crc_accumulator >> 8) & 0xff] ^
62+
crc64_table[5][(crc_accumulator >> 16) & 0xff] ^
63+
crc64_table[4][(crc_accumulator >> 24) & 0xff] ^
64+
crc64_table[3][(crc_accumulator >> 32) & 0xff] ^
65+
crc64_table[2][(crc_accumulator >> 40) & 0xff] ^
66+
crc64_table[1][(crc_accumulator >> 48) & 0xff] ^
67+
crc64_table[0][crc_accumulator >> 56];
68+
69+
data_len -= 8;
70+
}
71+
72+
for (size_t i = 0; i < data_len; ++i) {
73+
crc_accumulator = crc64_table[0][static_cast<uint8_t>(crc_accumulator) ^ data[i]] ^ (crc_accumulator >> 8);
74+
}
75+
76+
return ~crc_accumulator;
77+
}
78+
79+
constexpr operator uint64_t() const noexcept
80+
{ return crc_register_; }
81+
82+
private:
83+
uint64_t crc_register_ {0};
84+
85+
using CRC64_table_t = std::array<std::array<uint64_t, 256>, 8>;
86+
87+
static constexpr inline const CRC64_table_t get_table() noexcept {
88+
auto crc64_itable = get_init_table();
89+
90+
CRC64_table_t crc64_table;
91+
crc64_table[0] = crc64_itable;
92+
93+
for (uint64_t i = 0; i < 256; ++i) {
94+
auto crc_accumulator = crc64_itable[i];
95+
96+
for (uint64_t j = 1; j < 8; ++j) {
97+
crc_accumulator = crc64_itable[crc_accumulator & 0xff] ^ (crc_accumulator >> 8);
98+
crc64_table[j][i] = crc_accumulator;
99+
}
100+
}
101+
102+
return crc64_table;
103+
}
104+
105+
static constexpr inline const std::array<uint64_t, 256> get_init_table() noexcept {
106+
std::array<uint64_t, 256> data;
107+
108+
for (uint64_t i {0}; i < 256; ++i) {
109+
uint64_t crc {i};
110+
111+
for (uint64_t j {0}; j < 8; ++j) {
112+
if (crc & 1) {
113+
crc = (crc >> 1) ^ POLY;
114+
} else {
115+
crc >>= 1;
116+
}
117+
}
118+
119+
data[i] = crc;
120+
}
121+
122+
return data;
123+
}
124+
}; //< struct crc64
125+
126+
using crc64_iso_checksum = crc64<0xD800000000000000>; //< Specified in ISO 3309
127+
using crc64_ecma_checksum = crc64<0xC96C5795D7870F42>; //< Specified in ECMA 182
128+
129+
} //< namespace util
130+
131+
#endif //< UTIL_CRC64_HPP

0 commit comments

Comments
 (0)