@@ -24,102 +24,95 @@ open class FileHandle : NSObject, NSSecureCoding {
24
24
}
25
25
26
26
open var availableData : Data {
27
- return _readDataOfLength ( Int . max, untilEOF: false )
27
+ do {
28
+ let readResult = try _readDataOfLength ( Int . max, untilEOF: false )
29
+ return readResult. toData ( )
30
+ } catch {
31
+ fatalError ( " \( error) " )
32
+ }
28
33
}
29
34
30
35
open func readDataToEndOfFile( ) -> Data {
31
36
return readData ( ofLength: Int . max)
32
37
}
33
38
34
39
open func readData( ofLength length: Int ) -> Data {
35
- return _readDataOfLength ( length, untilEOF: true )
40
+ do {
41
+ let readResult = try _readDataOfLength ( length, untilEOF: true )
42
+ return readResult. toData ( )
43
+ } catch {
44
+ fatalError ( " \( error) " )
45
+ }
36
46
}
37
47
38
- internal func _readDataOfLength( _ length: Int , untilEOF: Bool ) -> Data {
48
+ internal func _readDataOfLength( _ length: Int , untilEOF: Bool , options : NSData . ReadingOptions = [ ] ) throws -> NSData . NSDataReadResult {
39
49
precondition ( _fd >= 0 , " Bad file descriptor " )
50
+ if length == 0 && !untilEOF {
51
+ // Nothing requested, return empty response
52
+ return NSData . NSDataReadResult ( bytes: nil , length: 0 , deallocator: nil )
53
+ }
54
+
40
55
var statbuf = stat ( )
41
- var dynamicBuffer : UnsafeMutableRawPointer ? = nil
42
- var total = 0
43
56
if fstat ( _fd, & statbuf) < 0 {
44
- fatalError ( " Unable to read file " )
57
+ throw NSError ( domain : NSPOSIXErrorDomain , code : Int ( errno ) , userInfo : nil )
45
58
}
46
- if statbuf. st_mode & S_IFMT != S_IFREG {
47
- /* We get here on sockets, character special files, FIFOs ... */
48
- var currentAllocationSize : size_t = 1024 * 8
49
- dynamicBuffer = malloc ( currentAllocationSize)
50
- var remaining = length
51
- while remaining > 0 {
52
- let amountToRead = min ( 1024 * 8 , remaining)
53
- // Make sure there is always at least amountToRead bytes available in the buffer.
54
- if ( currentAllocationSize - total) < amountToRead {
55
- currentAllocationSize *= 2
56
- dynamicBuffer = _CFReallocf ( dynamicBuffer!, currentAllocationSize)
57
- if dynamicBuffer == nil {
58
- fatalError ( " unable to allocate backing buffer " )
59
+
60
+ let readBlockSize : Int
61
+ if statbuf. st_mode & S_IFMT == S_IFREG {
62
+ // TODO: Should files over a certain size always be mmap()'d?
63
+ if options. contains ( . alwaysMapped) {
64
+ // Filesizes are often 64bit even on 32bit systems
65
+ let mapSize = min ( length, Int ( clamping: statbuf. st_size) )
66
+ let data = mmap ( nil , mapSize, PROT_READ, MAP_PRIVATE, _fd, 0 )
67
+ // Swift does not currently expose MAP_FAILURE
68
+ if data != UnsafeMutableRawPointer ( bitPattern: - 1 ) {
69
+ return NSData . NSDataReadResult ( bytes: data!, length: mapSize) { buffer, length in
70
+ munmap ( buffer, length)
59
71
}
60
72
}
61
- let amtRead = read ( _fd, dynamicBuffer!. advanced ( by: total) , amountToRead)
62
- if 0 > amtRead {
63
- free ( dynamicBuffer)
64
- fatalError ( " read failure " )
65
- }
66
- if 0 == amtRead {
67
- break // EOF
68
- }
69
-
70
- total += amtRead
71
- remaining -= amtRead
72
-
73
- if total == length || !untilEOF {
74
- break // We read everything the client asked for.
75
- }
73
+ }
74
+
75
+ if statbuf. st_blksize > 0 {
76
+ readBlockSize = Int ( clamping: statbuf. st_blksize)
77
+ } else {
78
+ readBlockSize = 1024 * 8
76
79
}
77
80
} else {
78
- let offset = lseek ( _fd, 0 , SEEK_CUR)
79
- if offset < 0 {
80
- fatalError ( " Unable to fetch current file offset " )
81
+ /* We get here on sockets, character special files, FIFOs ... */
82
+ readBlockSize = 1024 * 8
83
+ }
84
+ var currentAllocationSize = readBlockSize
85
+ var dynamicBuffer = malloc ( currentAllocationSize) !
86
+ var total = 0
87
+
88
+ while total < length {
89
+ let remaining = length - total
90
+ let amountToRead = min ( readBlockSize, remaining)
91
+ // Make sure there is always at least amountToRead bytes available in the buffer.
92
+ if ( currentAllocationSize - total) < amountToRead {
93
+ currentAllocationSize *= 2
94
+ dynamicBuffer = _CFReallocf ( dynamicBuffer, currentAllocationSize)
81
95
}
82
- if off_t ( statbuf. st_size) > offset {
83
- var remaining = size_t ( off_t ( statbuf. st_size) - offset)
84
- remaining = min ( remaining, size_t ( length) )
85
-
86
- dynamicBuffer = malloc ( remaining)
87
- if dynamicBuffer == nil {
88
- fatalError ( " Malloc failure " )
89
- }
90
-
91
- while remaining > 0 {
92
- let count = read ( _fd, dynamicBuffer!. advanced ( by: total) , remaining)
93
- if count < 0 {
94
- free ( dynamicBuffer)
95
- fatalError ( " Unable to read from fd " )
96
- }
97
- if count == 0 {
98
- break
99
- }
100
- total += count
101
- remaining -= count
102
- }
96
+ let amtRead = read ( _fd, dynamicBuffer. advanced ( by: total) , amountToRead)
97
+ if amtRead < 0 {
98
+ free ( dynamicBuffer)
99
+ throw NSError ( domain: NSPOSIXErrorDomain, code: Int ( errno) , userInfo: nil )
100
+ }
101
+ total += amtRead
102
+ if amtRead == 0 || !untilEOF { // If there is nothing more to read or we shouldnt keep reading then exit
103
+ break
103
104
}
104
105
}
105
106
106
- if length == Int . max && total > 0 {
107
- dynamicBuffer = _CFReallocf ( dynamicBuffer!, total)
108
- }
109
-
110
107
if total == 0 {
111
108
free ( dynamicBuffer)
109
+ return NSData . NSDataReadResult ( bytes: nil , length: 0 , deallocator: nil )
112
110
}
113
- else if total > 0 {
114
- let bytePtr = dynamicBuffer!. bindMemory ( to: UInt8 . self, capacity: total)
115
- return Data ( bytesNoCopy: bytePtr, count: total, deallocator: . free)
116
- }
117
- else {
118
- assertionFailure ( " The total number of read bytes must not be negative " )
119
- free ( dynamicBuffer)
111
+ dynamicBuffer = _CFReallocf ( dynamicBuffer, total)
112
+ let bytePtr = dynamicBuffer. bindMemory ( to: UInt8 . self, capacity: total)
113
+ return NSData . NSDataReadResult ( bytes: bytePtr, length: total) { buffer, length in
114
+ free ( buffer)
120
115
}
121
-
122
- return Data ( )
123
116
}
124
117
125
118
open func write( _ data: Data ) {
0 commit comments