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