1313import Swift
1414import SwiftShims
1515
16+ #if os(Windows)
17+ import MSVCRT
18+ import WinSDK
19+ #endif
20+
21+ #if os(Windows)
22+ public struct _FDInputStream {
23+ public var handle : HANDLE = INVALID_HANDLE_VALUE
24+ public var isEOF : Bool = false
25+ public var isClosed : Bool { return handle == INVALID_HANDLE_VALUE }
26+
27+ internal var _buffer : ContiguousArray < UInt8 > =
28+ ContiguousArray < UInt8 > ( repeating: 0 , count: 256 )
29+ internal var _offset : Int = 0
30+
31+ public init ( handle: HANDLE ) {
32+ self . handle = handle
33+ }
34+
35+ public mutating func getline( ) -> String ? {
36+ // FIXME(compnerd) Windows uses \r\n for the line delimiter, we should split
37+ // on that and remove the workaround in the test harness
38+ if let index =
39+ _buffer [ 0 ..< _offset] . firstIndex ( of: UInt8 ( Unicode . Scalar ( " \n " ) . value) ) {
40+ let result = String ( decoding: _buffer [ 0 ..< index] , as: UTF8 . self)
41+ _buffer. removeSubrange ( 0 ... index)
42+ _offset -= index + 1
43+ return result
44+ }
45+ if isEOF && _offset > 0 {
46+ let result = String ( decoding: _buffer [ 0 ..< _offset] , as: UTF8 . self)
47+ _buffer. removeAll ( )
48+ _offset = 0
49+ return result
50+ }
51+ return nil
52+ }
53+
54+ public mutating func read( ) {
55+ var space = _buffer. count - _offset
56+ if space < 128 {
57+ let capacity = _buffer. count + ( 128 - space)
58+ _buffer. reserveCapacity ( capacity)
59+ for _ in _buffer. count..< capacity {
60+ _buffer. append ( 0 )
61+ }
62+ space = 128
63+ }
64+ let read : Int = _buffer. withUnsafeMutableBufferPointer { buffer in
65+ var read : DWORD = 0
66+ ReadFile ( handle, buffer. baseAddress! + _offset, DWORD ( space) , & read, nil )
67+ return Int ( read)
68+ }
69+ if read == 0 {
70+ isEOF = true
71+ } else {
72+ _offset += read
73+ }
74+ }
75+
76+ public mutating func close( ) {
77+ if isClosed { return }
78+ CloseHandle ( handle)
79+ handle = INVALID_HANDLE_VALUE
80+ }
81+ }
82+ #else
1683public struct _FDInputStream {
1784 public let fd : CInt
1885 public var isClosed : Bool = false
@@ -79,6 +146,7 @@ public struct _FDInputStream {
79146 isClosed = true
80147 }
81148}
149+ #endif
82150
83151public struct _Stderr : TextOutputStream {
84152 public init ( ) { }
@@ -90,6 +158,37 @@ public struct _Stderr : TextOutputStream {
90158 }
91159}
92160
161+ #if os(Windows)
162+ public struct _FDOutputStream : TextOutputStream {
163+ public var handle : HANDLE
164+
165+ public init ( handle: HANDLE ) {
166+ self . handle = handle
167+ }
168+
169+ public mutating func write( _ string: String ) {
170+ string. utf8CString. withUnsafeBufferPointer { buffer in
171+ let dwLength : DWORD = DWORD ( buffer. count - 1 )
172+ var dwOffset : DWORD = 0
173+ while dwOffset < dwLength {
174+ var dwBytesWritten : DWORD = 0
175+ if WriteFile ( handle,
176+ UnsafeRawPointer ( buffer. baseAddress! + Int( dwOffset) ) ,
177+ dwLength - dwOffset, & dwBytesWritten, nil ) == FALSE {
178+ fatalError ( " WriteFile() failed " )
179+ }
180+ dwOffset += dwBytesWritten
181+ }
182+ }
183+ }
184+
185+ public mutating func close( ) {
186+ if handle == INVALID_HANDLE_VALUE { return }
187+ CloseHandle ( handle)
188+ handle = INVALID_HANDLE_VALUE
189+ }
190+ }
191+ #else
93192public struct _FDOutputStream : TextOutputStream {
94193 public let fd : CInt
95194 public var isClosed : Bool = false
@@ -127,3 +226,4 @@ public struct _FDOutputStream : TextOutputStream {
127226 isClosed = true
128227 }
129228}
229+ #endif
0 commit comments