@@ -2377,46 +2377,123 @@ extension FileManager {
2377
2377
self . innerEnumerator = ie
2378
2378
}
2379
2379
2380
- @available ( Windows, deprecated, message: " Not Yet Implemented " )
2381
2380
override func nextObject( ) -> Any ? {
2382
2381
let o = innerEnumerator. nextObject ( )
2383
2382
guard let url = o as? URL else {
2384
2383
return nil
2385
2384
}
2386
2385
2387
2386
#if os(Windows)
2388
- NSUnimplemented ( )
2387
+ var relativePath = UnsafeMutableBufferPointer< WCHAR> . allocate( capacity: Int ( MAX_PATH) )
2388
+ defer { relativePath. deallocate ( ) }
2389
+ func withURLCString< Result> ( url: URL , _ f: ( UnsafePointer < WCHAR > ) -> Result ? ) -> Result ? {
2390
+ return url. withUnsafeFileSystemRepresentation { fsr in
2391
+ ( fsr. flatMap { String ( utf8String: $0) } ) ? . withCString ( encodedAs: UTF16 . self) { f ( $0) }
2392
+ }
2393
+ }
2394
+ let result = withURLCString ( url: baseURL) { pszFrom -> BOOL ? in
2395
+ withURLCString ( url: url) { pszTo in
2396
+ let fromAttrs = GetFileAttributesW ( pszFrom)
2397
+ let toAttrs = GetFileAttributesW ( pszTo)
2398
+ guard fromAttrs != INVALID_FILE_ATTRIBUTES, toAttrs != INVALID_FILE_ATTRIBUTES else {
2399
+ return FALSE
2400
+ }
2401
+ return PathRelativePathToW ( relativePath. baseAddress, pszFrom, fromAttrs, pszTo, toAttrs)
2402
+ }
2403
+ }
2404
+
2405
+ guard result == TRUE, let ( path, _) = String . decodeCString ( relativePath. baseAddress, as: UTF16 . self) else {
2406
+ return nil
2407
+ }
2389
2408
#else
2390
2409
let path = url. path. replacingOccurrences ( of: baseURL. path+ " / " , with: " " )
2391
- _currentItemPath = path
2392
- return path
2393
2410
#endif
2411
+ _currentItemPath = path
2412
+ return _currentItemPath
2394
2413
}
2395
2414
}
2396
2415
2397
- #if os(Windows)
2398
2416
internal class NSURLDirectoryEnumerator : DirectoryEnumerator {
2399
- internal typealias ErrorHandler = /* @escaping */ ( URL , Error ) -> Bool
2417
+ #if os(Windows)
2418
+ var _options : FileManager . DirectoryEnumerationOptions
2419
+ var _errorHandler : ( ( URL , Error ) -> Bool ) ?
2420
+ var _stack : [ URL ]
2421
+ var _current : URL ?
2422
+ var _rootDepth : Int
2400
2423
2401
- init ( url: URL , options: FileManager . DirectoryEnumerationOptions , errorHandler: ErrorHandler ? ) {
2424
+ init ( url: URL , options: FileManager . DirectoryEnumerationOptions , errorHandler: ( /* @escaping */ ( URL , Error ) -> Bool ) ? ) {
2425
+ _options = options
2426
+ _errorHandler = errorHandler
2427
+ _stack = [ url]
2428
+ _rootDepth = url. pathComponents. count
2429
+ }
2430
+
2431
+ override func nextObject( ) -> Any ? {
2432
+ func contentsOfDir( directory: URL ) -> [ URL ] ? {
2433
+ var ffd : WIN32_FIND_DATAW = WIN32_FIND_DATAW ( )
2434
+ let dirPath = directory. absoluteString + " \\ * "
2435
+ let h : HANDLE = dirPath. withCString ( encodedAs: UTF16 . self) {
2436
+ FindFirstFileW ( $0, & ffd)
2437
+ }
2438
+ guard h != INVALID_HANDLE_VALUE else { return nil }
2439
+ defer { FindClose ( h) }
2440
+
2441
+ var files : [ URL ] = [ ]
2442
+ repeat {
2443
+ let fileArr = Array < WCHAR > (
2444
+ UnsafeBufferPointer ( start: & ffd. cFileName. 0 ,
2445
+ count: MemoryLayout . size ( ofValue: ffd. cFileName) ) )
2446
+ let file = String ( decodingCString: fileArr, as: UTF16 . self)
2447
+ if file != " . "
2448
+ && file != " .. "
2449
+ && ( !_options. contains ( . skipsHiddenFiles)
2450
+ || ( ffd. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_HIDDEN) == 0 ) ) {
2451
+ files. append ( URL ( fileURLWithPath: " \( directory. absoluteString) \\ \( file) " ) )
2452
+ }
2453
+ } while ( FindNextFileW ( h, & ffd) != 0 )
2454
+ return files
2455
+ }
2456
+ while let url = _stack. popLast ( ) {
2457
+ if url. hasDirectoryPath && !_options. contains ( . skipsSubdirectoryDescendants) {
2458
+ guard let dirContents = contentsOfDir ( directory: url) ? . reversed ( ) else {
2459
+ if let handler = _errorHandler {
2460
+ let keepGoing = handler ( URL ( fileURLWithPath: url. absoluteString) ,
2461
+ _NSErrorWithWindowsError ( GetLastError ( ) , reading: true ) )
2462
+ if !keepGoing { return nil }
2463
+ }
2464
+ continue
2465
+ }
2466
+ _stack. append ( contentsOf: dirContents)
2467
+ }
2468
+ _current = url
2469
+ return url
2470
+ }
2471
+ return nil
2472
+ }
2473
+
2474
+ override var level : Int {
2475
+ return _rootDepth - ( _current? . pathComponents. count ?? _rootDepth)
2476
+ }
2477
+
2478
+ override func skipDescendants( ) {
2479
+ _options. insert ( . skipsSubdirectoryDescendants)
2402
2480
}
2403
- }
2404
2481
#else
2405
- internal class NSURLDirectoryEnumerator : DirectoryEnumerator {
2406
2482
var _url : URL
2407
2483
var _options : FileManager . DirectoryEnumerationOptions
2408
2484
var _errorHandler : ( ( URL , Error ) -> Bool ) ?
2409
2485
var _stream : UnsafeMutablePointer < FTS > ? = nil
2410
2486
var _current : UnsafeMutablePointer < FTSENT > ? = nil
2411
2487
var _rootError : Error ? = nil
2412
2488
var _gotRoot : Bool = false
2413
-
2489
+
2490
+
2414
2491
// See @escaping comments above.
2415
2492
init ( url: URL , options: FileManager . DirectoryEnumerationOptions , errorHandler: ( /* @escaping */ ( URL , Error ) -> Bool ) ? ) {
2416
2493
_url = url
2417
2494
_options = options
2418
2495
_errorHandler = errorHandler
2419
-
2496
+
2420
2497
if FileManager . default. fileExists ( atPath: _url. path) {
2421
2498
let fsRep = FileManager . default. fileSystemRepresentation ( withPath: _url. path)
2422
2499
let ps = UnsafeMutablePointer< UnsafeMutablePointer< Int8>?> . allocate( capacity: 2 )
@@ -2430,15 +2507,15 @@ extension FileManager {
2430
2507
_rootError = _NSErrorWithErrno ( ENOENT, reading: true , url: url)
2431
2508
}
2432
2509
}
2433
-
2510
+
2434
2511
deinit {
2435
2512
if let stream = _stream {
2436
2513
fts_close ( stream)
2437
2514
}
2438
2515
}
2439
-
2440
- override func nextObject( ) -> Any ? {
2441
2516
2517
+
2518
+ override func nextObject( ) -> Any ? {
2442
2519
func match( filename: String , to options: DirectoryEnumerationOptions , isDir: Bool ) -> ( Bool , Bool ) {
2443
2520
var showFile = true
2444
2521
var skipDescendants = false
@@ -2459,10 +2536,10 @@ extension FileManager {
2459
2536
2460
2537
2461
2538
if let stream = _stream {
2462
-
2539
+
2463
2540
if !_gotRoot {
2464
2541
_gotRoot = true
2465
-
2542
+
2466
2543
// Skip the root.
2467
2544
_current = fts_read ( stream)
2468
2545
}
@@ -2504,7 +2581,7 @@ extension FileManager {
2504
2581
_current = fts_read ( stream)
2505
2582
}
2506
2583
// TODO: Error handling if fts_read fails.
2507
-
2584
+
2508
2585
} else if let error = _rootError {
2509
2586
// Was there an error opening the stream?
2510
2587
if let handler = _errorHandler {
@@ -2513,24 +2590,21 @@ extension FileManager {
2513
2590
}
2514
2591
return nil
2515
2592
}
2516
-
2517
- override var directoryAttributes : [ FileAttributeKey : Any ] ? {
2518
- return nil
2519
- }
2520
-
2521
- override var fileAttributes : [ FileAttributeKey : Any ] ? {
2522
- return nil
2523
- }
2524
-
2525
2593
override var level : Int {
2526
2594
return Int ( _current? . pointee. fts_level ?? 0 )
2527
2595
}
2528
-
2596
+
2529
2597
override func skipDescendants( ) {
2530
2598
if let stream = _stream, let current = _current {
2531
2599
fts_set ( stream, current, FTS_SKIP)
2532
2600
}
2533
2601
}
2534
- }
2535
2602
#endif
2603
+ override var directoryAttributes : [ FileAttributeKey : Any ] ? {
2604
+ return nil
2605
+ }
2606
+ override var fileAttributes : [ FileAttributeKey : Any ] ? {
2607
+ return nil
2608
+ }
2609
+ }
2536
2610
}
0 commit comments