-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbzip2.cr
More file actions
53 lines (43 loc) · 1.48 KB
/
bzip2.cr
File metadata and controls
53 lines (43 loc) · 1.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
require "./memfile"
@[Link("bzip2")]
lib LibBzip2
alias BZFILE = Void
fun BZ2_bzReadOpen(bzerror : Pointer(Int32), f : Pointer(Void), verbosity : Int32, small : Int32, unused : Pointer(Void), nUnused : Int32) : Pointer(BZFILE)
fun BZ2_bzRead(bzerror : Pointer(Int32), b : Pointer(BZFILE), buf : Pointer(UInt8), len : Int32) : Int32
fun BZ2_bzReadClose(bzerror : Pointer(Int32), b : Pointer(BZFILE)) : Void
end
class Bzip2::Reader
@io : IO
@bzfile : Pointer(LibBzip2::BZFILE)
@bzerror : Pointer(Int32)
@file_ptr : Pointer(Void) # MemFile pointer
def initialize(io : IO)
@io = io
# Create a memory-backed FILE* pointer from IO
@file_ptr = MemFile.from_io(io)
raise "Could not map memfile" unless @file_ptr
@bzerror = Pointer(Int32).malloc(1)
@bzfile = LibBzip2.BZ2_bzReadOpen(@bzerror, @file_ptr, 0, 0, Pointer(Void).null, 0)
raise "Failed to open Bzip2 stream, error=#{@bzerror.value}" unless @bzfile
end
def getb_to_end : Bytes
result = Bytes.new(0)
buffer = Bytes.new(4096)
while true
bytes_read = LibBzip2.BZ2_bzRead(@bzerror, @bzfile, buffer.to_unsafe, buffer.size)
case @bzerror.value
when 0 # BZ_OK
result += buffer[0, bytes_read]
when 4 # BZ_STREAM_END
result += buffer[0, bytes_read] if bytes_read > 0
break
else
raise "BZ2_bzRead failed with error #{@bzerror.value}"
end
end
result
end
def finalize
LibBzip2.BZ2_bzReadClose(@bzerror, @bzfile)
end
end