-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmemfile.cr
More file actions
85 lines (75 loc) · 1.89 KB
/
memfile.cr
File metadata and controls
85 lines (75 loc) · 1.89 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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# memory map crystal IO to C interop FILE*
@[Link("c")]
lib LibC
alias FILE = Void
{% if flag?(:darwin) %}
fun funopen(
cookie : Void*,
readfn : (Void*, UInt8*, LibC::SizeT) -> LibC::SizeT,
writefn : Void*,
seekfn : (Void*, LibC::OffT, Int32) -> LibC::OffT,
closefn : (Void*) -> Int32
) : FILE*
{% else %}
fun fopencookie(
cookie : Void*,
mode : LibC::Char*,
ops : CookieIO
) : FILE*
struct CookieIO
read : (Void*, UInt8*, LibC::SizeT) -> LibC::SizeT
write : Void*
seek : (Void*, LibC::OffT, Int32) -> LibC::OffT
close : (Void*) -> Int32
end
{% end %}
end
module MemFile
class IOCookie
getter io : IO
def initialize(@io : IO)
end
end
def self.from_io(io : IO) : Pointer(LibC::FILE)
cookie = Box.box(IOCookie.new(io))
read_cb = ->(cookie_ptr : Void*, buf : UInt8*, size : LibC::SizeT) : LibC::SizeT {
wrapper = Box(IOCookie).unbox(cookie_ptr)
begin
bytes_read = wrapper.io.read(Slice.new(buf, size))
bytes_read.to_u64
rescue
0.to_u64
end
}
seek_cb = ->(cookie_ptr : Void*, offset : LibC::OffT, whence : Int32) : LibC::OffT {
wrapper = Box(IOCookie).unbox(cookie_ptr)
begin
wrapper.io.seek(offset, IO::Seek.new(whence))
wrapper.io.pos.to_i64
rescue
-1.to_i64
end
}
close_cb = ->(cookie_ptr : Void*) : Int32 {
Box(IOCookie).unbox(cookie_ptr) # let GC handle it
0
}
{% if flag?(:darwin) %}
LibC.funopen(
cookie.as(Void*),
read_cb,
Pointer(Void).null,
seek_cb,
close_cb
)
{% else %}
ops = LibC::CookieIO.new(
read: read_cb,
write: Pointer(Void).null,
seek: seek_cb,
close: close_cb
)
LibC.fopencookie(cookie.as(Void*), "r".to_unsafe, ops)
{% end %}
end
end