@@ -20,51 +20,56 @@ import Swift
20
20
21
21
enum FileImageSourceError : Error {
22
22
case posixError( Int32 )
23
- case truncatedRead
23
+ case outOfRangeRead
24
24
}
25
25
26
26
class FileImageSource : ImageSource {
27
- private var fd : Int32
27
+ private var _mapping : UnsafeRawBufferPointer
28
28
29
29
public var isMappedImage : Bool { return false }
30
30
31
31
private var _path : String
32
32
public var path : String ? { return _path }
33
33
34
- public lazy var bounds : Bounds ? = {
35
- let size = lseek ( fd, 0 , SEEK_END)
36
- if size < 0 {
37
- return nil
38
- }
39
- return Bounds ( base: 0 , size: Size ( size) )
40
- } ( )
34
+ public var bounds : Bounds ? {
35
+ return Bounds ( base: 0 , size: Size ( _mapping. count) )
36
+ }
41
37
42
38
public init ( path: String ) throws {
43
39
_path = path
44
- fd = _swift_open ( path, O_RDONLY, 0 )
40
+ let fd = _swift_open ( path, O_RDONLY, 0 )
45
41
if fd < 0 {
46
42
throw FileImageSourceError . posixError ( _swift_get_errno ( ) )
47
43
}
44
+ defer { close ( fd) }
45
+ let size = lseek ( fd, 0 , SEEK_END)
46
+ if size < 0 {
47
+ throw FileImageSourceError . posixError ( _swift_get_errno ( ) )
48
+ }
49
+ let base = mmap ( nil , Int ( size) , PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0 )
50
+ if base == nil || base! == UnsafeRawPointer ( bitPattern: - 1 ) ! {
51
+ throw FileImageSourceError . posixError ( _swift_get_errno ( ) )
52
+ }
53
+ _mapping = UnsafeRawBufferPointer ( start: base, count: Int ( size) )
48
54
}
49
55
50
56
deinit {
51
- close ( fd)
57
+ munmap ( UnsafeMutableRawPointer ( mutating: _mapping. baseAddress) ,
58
+ _mapping. count)
52
59
}
53
60
54
61
public func fetch< T> ( from addr: Address ,
55
62
into buffer: UnsafeMutableBufferPointer < T > ) throws {
56
- while true {
57
- let size = MemoryLayout < T > . stride * buffer. count
58
- let result = pread ( fd, buffer. baseAddress, size, off_t ( addr) )
59
-
60
- if result < 0 {
61
- throw FileImageSourceError . posixError ( _swift_get_errno ( ) )
63
+ let start = Int ( addr)
64
+ _ = try buffer. withMemoryRebound ( to: UInt8 . self) { byteBuf in
65
+ guard _mapping. indices. contains ( start) else {
66
+ throw FileImageSourceError . outOfRangeRead
62
67
}
63
-
64
- if result != size {
65
- throw FileImageSourceError . truncatedRead
68
+ let slice = _mapping [ start ... ]
69
+ guard slice . count >= byteBuf . count else {
70
+ throw FileImageSourceError . outOfRangeRead
66
71
}
67
- break
72
+ byteBuf . update ( from : slice )
68
73
}
69
74
}
70
75
}
0 commit comments