libnx  v4.6.0
crc.h
Go to the documentation of this file.
1 /**
2  * @file crc.h
3  * @brief Hardware accelerated CRC32 implementation.
4  * @copyright libnx Authors
5  */
6 #pragma once
7 #include <arm_acle.h>
8 #include "../types.h"
9 
10 #define _CRC_ALIGN(sz, insn) \
11 do { \
12  if (((uintptr_t)src_u8 & sizeof(sz)) && (u64)len >= sizeof(sz)) { \
13  crc = __crc32##insn(crc, *((const sz *)src_u8)); \
14  src_u8 += sizeof(sz); \
15  len -= sizeof(sz); \
16  } \
17 } while (0)
18 
19 #define _CRC_REMAINDER(sz, insn) \
20 do { \
21  if (len & sizeof(sz)) { \
22  crc = __crc32##insn(crc, *((const sz *)src_u8)); \
23  src_u8 += sizeof(sz); \
24  } \
25 } while (0)
26 
27 /// Calculate a CRC32 over data using a seed.
28 /// Can be used to calculate a CRC32 in chunks using an initial seed of zero for the first chunk.
29 static inline u32 crc32CalculateWithSeed(u32 seed, const void *src, size_t size) {
30  const u8 *src_u8 = (const u8 *)src;
31 
32  u32 crc = ~seed;
33  s64 len = size;
34 
35  _CRC_ALIGN(u8, b);
36  _CRC_ALIGN(u16, h);
37  _CRC_ALIGN(u32, w);
38 
39  while ((len -= sizeof(u64)) >= 0) {
40  crc = __crc32d(crc, *((const u64 *)src_u8));
41  src_u8 += sizeof(u64);
42  }
43 
44  _CRC_REMAINDER(u32, w);
45  _CRC_REMAINDER(u16, h);
46  _CRC_REMAINDER(u8, b);
47 
48  return ~crc;
49 }
50 
51 /// Calculate a CRC32 over data.
52 static inline u32 crc32Calculate(const void *src, size_t size) {
53  return crc32CalculateWithSeed(0, src, size);
54 }
55 
56 /// Calculate a CRC32C over data using a seed.
57 /// Can be used to calculate a CRC32C in chunks using an initial seed of zero for the first chunk.
58 static inline u32 crc32cCalculateWithSeed(u32 seed, const void *src, size_t size) {
59  const u8 *src_u8 = (const u8 *)src;
60 
61  u32 crc = ~seed;
62  s64 len = size;
63 
64  _CRC_ALIGN(u8, cb);
65  _CRC_ALIGN(u16, ch);
66  _CRC_ALIGN(u32, cw);
67 
68  while ((len -= sizeof(u64)) >= 0) {
69  crc = __crc32cd(crc, *((const u64 *)src_u8));
70  src_u8 += sizeof(u64);
71  }
72 
73  _CRC_REMAINDER(u32, cw);
74  _CRC_REMAINDER(u16, ch);
75  _CRC_REMAINDER(u8, cb);
76 
77  return ~crc;
78 }
79 
80 /// Calculate a CRC32C over data.
81 static inline u32 crc32cCalculate(const void *src, size_t size) {
82  return crc32cCalculateWithSeed(0, src, size);
83 }
84 
85 #undef _CRC_REMAINDER
86 #undef _CRC_ALIGN
static u32 crc32cCalculateWithSeed(u32 seed, const void *src, size_t size)
Calculate a CRC32C over data using a seed.
Definition: crc.h:58
static u32 crc32Calculate(const void *src, size_t size)
Calculate a CRC32 over data.
Definition: crc.h:52
static u32 crc32cCalculate(const void *src, size_t size)
Calculate a CRC32C over data.
Definition: crc.h:81
static u32 crc32CalculateWithSeed(u32 seed, const void *src, size_t size)
Calculate a CRC32 over data using a seed.
Definition: crc.h:29
int64_t s64
64-bit signed integer.
Definition: types.h:28
uint64_t u64
64-bit unsigned integer.
Definition: types.h:22
uint8_t u8
8-bit unsigned integer.
Definition: types.h:19
uint16_t u16
16-bit unsigned integer.
Definition: types.h:20
uint32_t u32
32-bit unsigned integer.
Definition: types.h:21