Skip to content

Commit b86ec97

Browse files
nhz2stevengj
andauthored
Support Memory{UInt8} and AbstractVector{UInt8} as input. (#12)
* Support Memory and AbstractVector as input. * fix CI * Update src/CRC32.jl Co-authored-by: Steven G. Johnson <stevenj@alum.mit.edu> * Update readme * Update src/CRC32.jl Co-authored-by: Steven G. Johnson <stevenj@alum.mit.edu> * remove unneeded type checks --------- Co-authored-by: Steven G. Johnson <stevenj@alum.mit.edu>
1 parent 98f7230 commit b86ec97

File tree

5 files changed

+49
-12
lines changed

5 files changed

+49
-12
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
schedule:
55
- cron: '0 2 * * *' # Daily at 2 AM UTC (8 PM CST)
66
push:
7-
branches: [master]
7+
branches: [main]
88
tags: ["*"]
99
pull_request:
1010
concurrency:

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ Zlib_jll = "83775a58-1f1d-513f-b197-d71354ab007a"
1010
julia = "1.3"
1111

1212
[extras]
13+
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
1314
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1415

1516
[targets]
16-
test = ["Test"]
17+
test = ["OffsetArrays", "Test"]

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ CRC-32 checksum.
2626
crc32(data, crc::UInt32=0x00000000)
2727
```
2828

29-
Computes the CRC-32 checksum (ISO 3309, ITU-T V.42, CRC-32-IEEE) of the given `data`, which can be
30-
an `Array{UInt8}`, a contiguous subarray thereof, or a `String`. Optionally, you can pass
31-
a starting `crc` integer to be mixed in with the checksum. The `crc` parameter
32-
can be used to compute a checksum on data divided into chunks: performing
29+
Compute the CRC-32 checksum (ISO 3309, ITU-T V.42, CRC-32-IEEE) of the given `data`, which can be
30+
an `Array{UInt8}`, a contiguous subarray thereof, an `AbstractVector{UInt8}`, or a `String`.
31+
Optionally, you can pass a starting `crc` integer to be mixed in with the checksum.
32+
The `crc` parameter can be used to compute a checksum on data divided into chunks: performing
3333
`crc32(data2, crc32(data1))` is equivalent to the checksum of `[data1; data2]`.
3434

3535
There is also a method `crc32(io, nb, crc)` to checksum `nb` bytes from

src/CRC32.jl

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,25 @@ module CRC32
1414
export crc32
1515

1616
# contiguous byte arrays compatible with C `unsigned char *` API of zlib
17-
const ByteArray = Union{Array{UInt8},
18-
Base.FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N,
19-
Base.CodeUnits{UInt8, String}, Base.CodeUnits{UInt8, SubString{String}}}
17+
if VERSION v"1.11"
18+
const ByteArray = Union{Array{UInt8},
19+
Memory{UInt8},
20+
Base.FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N,
21+
Base.FastContiguousSubArray{UInt8,1,Memory{UInt8}},
22+
Base.CodeUnits{UInt8, String}, Base.CodeUnits{UInt8, SubString{String}}}
23+
else
24+
const ByteArray = Union{Array{UInt8},
25+
Base.FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N,
26+
Base.CodeUnits{UInt8, String}, Base.CodeUnits{UInt8, SubString{String}}}
27+
end
2028

2129
"""
2230
crc32(data, crc::UInt32=0x00000000)
2331
2432
Compute the CRC-32 checksum (ISO 3309, ITU-T V.42, CRC-32-IEEE) of the given `data`, which can be
25-
an `Array{UInt8}`, a contiguous subarray thereof, or a `String`. Optionally, you can pass
26-
a starting `crc` integer to be mixed in with the checksum. The `crc` parameter
27-
can be used to compute a checksum on data divided into chunks: performing
33+
an `Array{UInt8}`, a contiguous subarray thereof, an `AbstractVector{UInt8}`, or a `String`.
34+
Optionally, you can pass a starting `crc` integer to be mixed in with the checksum.
35+
The `crc` parameter can be used to compute a checksum on data divided into chunks: performing
2836
`crc32(data2, crc32(data1))` is equivalent to the checksum of `[data1; data2]`.
2937
3038
There is also a method `crc32(io, nb, crc)` to checksum `nb` bytes from
@@ -39,6 +47,7 @@ For a `String`, note that the result is specific to the UTF-8 encoding
3947
function crc32 end
4048

4149
crc32(a::ByteArray, crc::UInt32=0x00000000) = _crc32(a, crc)
50+
crc32(a::AbstractVector{UInt8}, crc::UInt32=0x00000000) = _crc32(a, crc)
4251
crc32(s::Union{String, SubString{String}}, crc::UInt32=0x00000000) = _crc32(s, crc)
4352

4453
"""
@@ -66,6 +75,21 @@ function _crc32(s::Union{String, SubString{String}}, crc::UInt32=0x00000000)
6675
unsafe_crc32(s, sizeof(s) % Csize_t, crc)
6776
end
6877

78+
function _crc32(a::AbstractVector{UInt8}, crc::UInt32=0x00000000)
79+
# use block size 24576=8192*3, since that is the threshold for
80+
# 3-way parallel SIMD code in the underlying jl_crc32 C function.
81+
last = lastindex(a)
82+
nb = length(a)
83+
buf = Vector{UInt8}(undef, min(nb, 24576))
84+
while nb > 0
85+
n = min(nb, 24576)
86+
copyto!(buf, 1, a, last - nb + 1, n)
87+
crc = unsafe_crc32(buf, n % Csize_t, crc)
88+
nb -= n
89+
end
90+
return crc
91+
end
92+
6993
function _crc32(io::IO, nb::Integer, crc::UInt32=0x00000000)
7094
nb < 0 && throw(ArgumentError("number of bytes to checksum must be ≥ 0, got $nb"))
7195
# use block size 24576=8192*3, since that is the threshold for

test/runtests.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CRC32
22
using Test
3+
using OffsetArrays: Origin
34

45
# based on julia/stdlib/CRC32/test/runtests.jl
56

@@ -9,6 +10,12 @@ using Test
910
s = String(UInt8[1:n;])
1011
ss = SubString(String(UInt8[0:(n+1);]), 2:(n+1))
1112
@test crc32(UInt8[1:n;]) == crc == crc32(s) == crc32(ss) == crc32(codeunits(s)) == crc32(codeunits(ss))
13+
@test crc == crc32(UInt8(1):UInt8(n))
14+
if VERSION v"1.11"
15+
m = Memory{UInt8}(undef, n)
16+
m .= 1:n
17+
@test crc == crc32(m)
18+
end
1219
end
1320

1421
# test that crc parameter is equivalent to checksum of concatenated data,
@@ -59,4 +66,9 @@ using Test
5966
if Sys.WORD_SIZE == 64
6067
@test crc32(zeros(UInt8, 2^32)) == 0xd202ef8d #crc32(zeros(UInt8, 2^31), crc32(zeros(UInt8, 2^31)))
6168
end
69+
70+
# Test crc of AbstractVector{UInt8}
71+
a = view(rand(UInt8, 300000), 1:2:300000)
72+
@test crc32(a) == crc32(collect(a))
73+
@test crc32(Origin(0)(b"hello")) == crc32(b"hello")
6274
end

0 commit comments

Comments
 (0)