@@ -20,51 +20,54 @@ import Swift
2020
2121enum FileImageSourceError : Error {
2222 case posixError( Int32 )
23- case truncatedRead
23+ case outOfRangeRead
2424}
2525
2626class FileImageSource : ImageSource {
27- private var fd : Int32
27+ private var _fd : Int32
28+ private var _mapping : UnsafeRawBufferPointer
2829
2930 public var isMappedImage : Bool { return false }
3031
3132 private var _path : String
3233 public var path : String ? { return _path }
3334
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+ }
4138
4239 public init ( path: String ) throws {
4340 _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 {
4647 throw FileImageSourceError . posixError ( _swift_get_errno ( ) )
4748 }
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) )
4854 }
4955
5056 deinit {
51- close ( fd)
57+ munmap ( UnsafeMutableRawPointer ( mutating: _mapping. baseAddress) ,
58+ _mapping. count)
59+ close ( _fd)
5260 }
5361
5462 public func fetch< T> ( from addr: Address ,
5563 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)
6871 }
6972 }
7073}
0 commit comments