@@ -20,51 +20,54 @@ 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 _fd : Int32
28
+ private var _mapping : UnsafeRawBufferPointer
28
29
29
30
public var isMappedImage : Bool { return false }
30
31
31
32
private var _path : String
32
33
public var path : String ? { return _path }
33
34
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
- } ( )
35
+ public var bounds : Bounds ? {
36
+ return Bounds ( base: 0 , size: Size ( _mapping. count) )
37
+ }
41
38
42
39
public init ( path: String ) throws {
43
40
_path = path
44
- fd = _swift_open ( path, O_RDONLY, 0 )
45
- if fd < 0 {
41
+ _fd = _swift_open ( path, O_RDONLY, 0 )
42
+ if _fd < 0 {
43
+ throw FileImageSourceError . posixError ( _swift_get_errno ( ) )
44
+ }
45
+ let size = lseek ( _fd, 0 , SEEK_END)
46
+ if size < 0 {
46
47
throw FileImageSourceError . posixError ( _swift_get_errno ( ) )
47
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)
59
+ close ( _fd)
52
60
}
53
61
54
62
public func fetch< T> ( from addr: Address ,
55
63
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 ( ) )
62
- }
63
-
64
- if result != size {
65
- throw FileImageSourceError . truncatedRead
66
- }
67
- break
64
+ let size = buffer. count * MemoryLayout< T> . stride
65
+ guard Int ( addr) < _mapping. count && _mapping. count - Int( addr) >= size else {
66
+ throw FileImageSourceError . outOfRangeRead
67
+ }
68
+ let slice = _mapping [ Int ( addr) ... ]
69
+ _ = buffer. withMemoryRebound ( to: UInt8 . self) { byteBuf in
70
+ byteBuf. update ( from: slice)
68
71
}
69
72
}
70
73
}
0 commit comments