Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 57 additions & 28 deletions src/ZipFile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -439,29 +439,69 @@ function close(f::ReadableFile)
nothing
end

"create underlying Zlib reader if doesn't exist"
function ensure_zio!(f::ReadableFile)
f._datapos >= 0 && return

seek(f._io, f._offset)
if readle(f._io, UInt32) != _LocalFileHdrSig
error("invalid file header")
end
skip(f._io, 2+2+2+2+2+4+4+4)
filelen = readle(f._io, UInt16)
extralen = readle(f._io, UInt16)
skip(f._io, filelen+extralen)
if f.method == Deflate
f._zio = Zlib.Reader(f._io, true)
elseif f.method == Store
f._zio = f._io
end
f._datapos = position(f._io)
end

"advance io position state and crc32 checksum, checking it at eof"
function update_reader!(f::ReadableFile, data::Array{UInt8})
f._zpos = position(f._io) - f._datapos
f._pos += length(data)
f._currentcrc32 = Zlib.crc32(data, f._currentcrc32)

if eof(f)
if f.method == Deflate
close(f._zio)
end
if f._currentcrc32 != f.crc32
error("crc32 do not match")
end
end
end
update_reader!(f::ReadableFile, data::UInt8) = update_reader!(f, [data])


# Read data into a. Throws EOFError if a cannot be filled in completely.
read(f::ReadableFile, a::Array{T}) where T = read!(f, Array{T}(undef, size(a)))

read!(f::ReadableFile, a::Array{UInt8}) = _read(f, a)
read!(f::ReadableFile, a::Array{T}) where T = _read(f, a)

function read(f::ReadableFile, ::Type{UInt8})
ensure_zio!(f)
seek(f._io, f._datapos+f._zpos)
byte = read(f._zio, UInt8)
update_reader!(f, byte)
byte
end

function Base.unsafe_read(f::ReadableFile, p::Ptr{UInt8}, n::UInt)
ensure_zio!(f)
seek(f._io, f._datapos+f._zpos)
b = unsafe_wrap(Array{UInt8, 1}, p, n)
read!(f._zio, b)
update_reader!(f, b)
nothing
end

function _read(f::ReadableFile, a::Array{T}) where T
if f._datapos < 0
seek(f._io, f._offset)
if readle(f._io, UInt32) != _LocalFileHdrSig
error("invalid file header")
end
skip(f._io, 2+2+2+2+2+4+4+4)
filelen = readle(f._io, UInt16)
extralen = readle(f._io, UInt16)
skip(f._io, filelen+extralen)
if f.method == Deflate
f._zio = Zlib.Reader(f._io, true)
elseif f.method == Store
f._zio = f._io
end
f._datapos = position(f._io)
end
ensure_zio!(f)

if eof(f) || f._pos+length(a)*sizeof(T) > f.uncompressedsize
throw(EOFError())
Expand All @@ -470,18 +510,7 @@ function _read(f::ReadableFile, a::Array{T}) where T
seek(f._io, f._datapos+f._zpos)
b = unsafe_wrap(Array{UInt8, 1}, reinterpret(Ptr{UInt8}, pointer(a)), sizeof(a))
read!(f._zio, b)
f._zpos = position(f._io) - f._datapos
f._pos += length(b)
f._currentcrc32 = Zlib.crc32(b, f._currentcrc32)

if eof(f)
if f.method == Deflate
close(f._zio)
end
if f._currentcrc32 != f.crc32
error("crc32 do not match")
end
end
update_reader!(f, b)

return a
end
Expand Down
11 changes: 1 addition & 10 deletions src/iojunk.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
# Writer the byte b in w.
function write(w::WritableFile, b::UInt8)
write(w, Ref(b))
end

# Read and return a byte from f. Throws EOFError if there is no more byte to read.
function read(f::ReadableFile, ::Type{UInt8})
# This function needs to be fast because readbytes, readstring, etc.
# uses it. Avoid function calls when possible.
b = Vector{UInt8}(undef, 1)
c = read(f, b)
c[1]
end
end