Răsfoiți Sursa

Java like file API replaced by extension methods around String.

Damian Kołakowski 9 ani în urmă
părinte
comite
caf411abb5

+ 0 - 162
Sources/Swifter/File.swift

@@ -1,162 +0,0 @@
-//
-//  File.swift
-//  Swifter
-//
-//  Copyright (c) 2014-2016 Damian Kołakowski. All rights reserved.
-//
-
-#if os(Linux)
-    import Glibc
-#else
-    import Foundation
-#endif
-
-public enum FileError: Error {
-    case openFailed(String)
-    case writeFailed(String)
-    case readFailed(String)
-    case seekFailed(String)
-    case getCurrentWorkingDirectoryFailed(String)
-    case isDirectoryFailed(String)
-    case openDirFailed(String)
-}
-
-public class File {
-    
-    public static var PATH_SEPARATOR = "/"
-    
-    public static func openNewForWriting(_ path: String) throws -> File {
-        return try openFileForMode(path, "wb")
-    }
-    
-    public static func openForReading(_ path: String) throws -> File {
-        return try openFileForMode(path, "rb")
-    }
-    
-    public static func openForWritingAndReading(_ path: String) throws -> File {
-        return try openFileForMode(path, "r+b")
-    }
-    
-    public static func openFileForMode(_ path: String, _ mode: String) throws -> File {
-        guard let file = path.withCString({ pathPointer in mode.withCString({ fopen(pathPointer, $0) }) }) else {
-            throw FileError.openFailed(descriptionOfLastError())
-        }
-        return File(file)
-    }
-    
-    public static func isDirectory(_ path: String) throws -> Bool {
-        var s = stat()
-        guard stat(path, &s) == 0 else {
-            throw FileError.isDirectoryFailed(descriptionOfLastError())
-        }
-        return s.st_mode & S_IFMT == S_IFDIR
-    }
-    
-    public static func currentWorkingDirectory() throws -> String {
-        guard let path = getcwd(nil, 0) else {
-            throw FileError.getCurrentWorkingDirectoryFailed(descriptionOfLastError())
-        }
-        return String(cString: path)
-    }
-    
-    public static func exists(_ path: String) throws -> Bool {
-        var buffer = stat()
-        return path.withCString({ stat($0, &buffer) == 0 })
-    }
-    
-    public static func list(_ path: String) throws -> [String] {
-        let dir = path.withCString { opendir($0) }
-        if dir == nil {
-            throw FileError.openDirFailed(descriptionOfLastError())
-        }
-        defer { closedir(dir) }
-        var results = [String]()
-        while true {
-            guard let ent = readdir(dir) else {
-                break
-            }
-            var name = ent.pointee.d_name
-            let fileName = withUnsafePointer(to: &name) { (ptr) -> String? in
-                #if os(Linux)
-                    return String.fromCString([CChar](UnsafeBufferPointer<CChar>(start: UnsafePointer(unsafeBitCast(ptr, UnsafePointer<CChar>.self)), count: 256)))
-                #else
-                    var buffer = [CChar](UnsafeBufferPointer(start: unsafeBitCast(ptr, to: UnsafePointer<CChar>.self), count: Int(ent.pointee.d_namlen)))
-                    buffer.append(0)
-                    return String(validatingUTF8: buffer)
-                #endif
-            }
-            if let fileName = fileName {
-                results.append(fileName)
-            }
-        }
-        return results
-    }
-    
-    internal let pointer: UnsafeMutablePointer<FILE>
-    
-    public init(_ pointer: UnsafeMutablePointer<FILE>) {
-        self.pointer = pointer
-    }
-    
-    public func close() -> Void {
-        fclose(pointer)
-    }
-    
-    public func read(_ data: inout [UInt8]) throws -> Int {
-        if data.count <= 0 {
-            return data.count
-        }
-        let count = fread(&data, 1, data.count, self.pointer)
-        if count == data.count {
-            return count
-        }
-        if feof(self.pointer) != 0 {
-            return count
-        }
-        if ferror(self.pointer) != 0 {
-            throw FileError.readFailed(File.descriptionOfLastError())
-        }
-        throw FileError.readFailed("Unknown file read error occured.")
-    }
-
-    public func write(_ data: [UInt8]) throws -> Void {
-        if data.count <= 0 {
-            return
-        }
-        try data.withUnsafeBufferPointer {
-            if fwrite($0.baseAddress, 1, data.count, self.pointer) != data.count {
-                throw FileError.writeFailed(File.descriptionOfLastError())
-            }
-        }
-    }
-    
-    public func seek(_ offset: Int) throws -> Void {
-        if fseek(self.pointer, offset, SEEK_SET) != 0 {
-            throw FileError.seekFailed(File.descriptionOfLastError())
-        }
-    }
-    
-    private static func descriptionOfLastError() -> String {
-        return String(cString: UnsafePointer(strerror(errno)))
-    }
-}
-
-public func withNewFileOpenedForWriting<Result>(path: String, _ f: (File) throws -> Result) throws -> Result {
-    return try withFileOpenedForMode(path, "wb", f)
-}
-
-public func withFileOpenedForReading<Result>(path: String, _ f: (File) throws -> Result) throws -> Result {
-    return try withFileOpenedForMode(path, "rb", f)
-}
-
-public func withFileOpenedForWritingAndReading<Result>(path: String, _ f: (File) throws -> Result) throws -> Result {
-    return try withFileOpenedForMode(path, "r+b", f)
-}
-
-public func withFileOpenedForMode<Result>(_ path: String, _ mode: String, _ f: (File) throws -> Result) throws -> Result {
-    let file = try File.openFileForMode(path, mode)
-    defer {
-        file.close()
-    }
-    return try f(file)
-}

+ 8 - 8
Sources/Swifter/Files.swift

@@ -14,7 +14,7 @@ public func shareFilesFromDirectory(_ directoryPath: String, defaults: [String]
         }
         if fileRelativePath.value.isEmpty {
             for path in defaults {
-                if let file = try? File.openForReading(directoryPath + File.PATH_SEPARATOR + path) {
+                if let file = try? (directoryPath + String.PATH_SEPARATOR + path).openForReading() {
                     return .raw(200, "OK", [:], { writer in
                         try? writer.write(file)
                         file.close()
@@ -22,7 +22,7 @@ public func shareFilesFromDirectory(_ directoryPath: String, defaults: [String]
                 }
             }
         }
-        if let file = try? File.openForReading(directoryPath + File.PATH_SEPARATOR + fileRelativePath.value) {
+        if let file = try? (directoryPath + String.PATH_SEPARATOR + fileRelativePath.value).openForReading() {
             return .raw(200, "OK", [:], { writer in
                 try? writer.write(file)
                 file.close()
@@ -37,13 +37,13 @@ public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) {
         guard let (_, value) = r.params.first else {
             return HttpResponse.notFound
         }
-        let filePath = dir + File.PATH_SEPARATOR + value
+        let filePath = dir + String.PATH_SEPARATOR + value
         do {
-            guard try File.exists(filePath) else {
-                return HttpResponse.notFound
+            guard try filePath.exists() else {
+                return .notFound
             }
-            if try File.isDirectory(filePath) {
-                let files = try File.list(filePath)
+            if try filePath.directory() {
+                let files = try filePath.files()
                 return scopes {
                     html {
                         body {
@@ -61,7 +61,7 @@ public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) {
                     }
                 }(r)
             } else {
-                guard let file = try? File.openForReading(filePath) else {
+                guard let file = try? filePath.openForReading() else {
                     return .notFound
                 }
                 return .raw(200, "OK", [:], { writer in

+ 1 - 1
Sources/Swifter/HttpResponse.swift

@@ -13,7 +13,7 @@ public enum SerializationError: Error {
 }
 
 public protocol HttpResponseBodyWriter {
-    func write(_ file: File) throws
+    func write(_ file: String.File) throws
     func write(_ data: [UInt8]) throws
     func write(_ data: ArraySlice<UInt8>) throws
 }

+ 1 - 1
Sources/Swifter/HttpServerIO.swift

@@ -90,7 +90,7 @@ public class HttpServerIO {
     private struct InnerWriteContext: HttpResponseBodyWriter {
         let socket: Socket
         
-        func write(_ file: File) throws {
+        func write(_ file: String.File) throws {
             var offset: off_t = 0
             let _ = sendfile(fileno(file.pointer), socket.socketFileDescriptor, 0, &offset, nil, 0)
         }

+ 1 - 1
Sources/Swifter/Socket+File.swift

@@ -42,7 +42,7 @@
 
 extension Socket {
     
-    public func writeFile(file: File) throws -> Void {
+    public func writeFile(file: String.File) throws -> Void {
         var offset: off_t = 0
         let result = sendfileImpl(fileno(file.pointer), self.socketFileDescriptor, 0, &offset, nil, 0)
         if result == -1 {

+ 139 - 0
Sources/Swifter/String+File.swift

@@ -0,0 +1,139 @@
+//
+//  String+File.swift
+//  Swifter
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+import Foundation
+
+extension String {
+    
+    public enum FileError: Error {
+        case error(Int32)
+    }
+    
+    public class File {
+        
+        internal let pointer: UnsafeMutablePointer<FILE>
+        
+        public init(_ pointer: UnsafeMutablePointer<FILE>) {
+            self.pointer = pointer
+        }
+        
+        public func close() -> Void {
+            fclose(pointer)
+        }
+        
+        public func read(_ data: inout [UInt8]) throws -> Int {
+            if data.count <= 0 {
+                return data.count
+            }
+            let count = fread(&data, 1, data.count, self.pointer)
+            if count == data.count {
+                return count
+            }
+            if feof(self.pointer) != 0 {
+                return count
+            }
+            if ferror(self.pointer) != 0 {
+                throw FileError.error(errno)
+            }
+            throw FileError.error(0)
+        }
+        
+        public func write(_ data: [UInt8]) throws -> Void {
+            if data.count <= 0 {
+                return
+            }
+            try data.withUnsafeBufferPointer {
+                if fwrite($0.baseAddress, 1, data.count, self.pointer) != data.count {
+                    throw FileError.error(errno)
+                }
+            }
+        }
+    }
+
+    public static var PATH_SEPARATOR = "/"
+    
+    public func openNewForWriting() throws -> File {
+        return try openFileForMode(self, "wb")
+    }
+    
+    public func openForReading() throws -> File {
+        return try openFileForMode(self, "rb")
+    }
+    
+    public func openForWritingAndReading() throws -> File {
+        return try openFileForMode(self, "r+b")
+    }
+    
+    public func openFileForMode(_ path: String, _ mode: String) throws -> File {
+        guard let file = path.withCString({ pathPointer in mode.withCString({ fopen(pathPointer, $0) }) }) else {
+            throw FileError.error(errno)
+        }
+        return File(file)
+    }
+    
+    public func exists() throws -> Bool {
+        return try self.withStat {
+            if let _ = $0 {
+                return true
+            }
+            return false
+        }
+    }
+    
+    public func directory() throws -> Bool {
+        return try self.withStat {
+            if let stat = $0 {
+                return stat.st_mode & S_IFMT == S_IFDIR
+            }
+            return false
+        }
+    }
+    
+    public func files() throws -> [String] {
+        guard let dir = self.withCString({ opendir($0) }) else {
+            throw FileError.error(errno)
+        }
+        defer { closedir(dir) }
+        var results = [String]()
+        while let ent = readdir(dir) {
+            var name = ent.pointee.d_name
+            let fileName = withUnsafePointer(to: &name) { (ptr) -> String? in
+                #if os(Linux)
+                    return String.fromCString([CChar](UnsafeBufferPointer<CChar>(start: UnsafePointer(unsafeBitCast(ptr, UnsafePointer<CChar>.self)), count: 256)))
+                #else
+                    var buffer = [CChar](UnsafeBufferPointer(start: unsafeBitCast(ptr, to: UnsafePointer<CChar>.self), count: Int(ent.pointee.d_namlen)))
+                    buffer.append(0)
+                    return String(validatingUTF8: buffer)
+                #endif
+            }
+            if let fileName = fileName {
+                results.append(fileName)
+            }
+        }
+        return results
+    }
+    
+    public static func currentWorkingDirectory() throws -> String {
+        guard let path = getcwd(nil, 0) else {
+            throw FileError.error(errno)
+        }
+        return String(cString: path)
+    }
+
+    private func withStat<T>(_ closure: ((stat?) throws -> T)) throws -> T {
+        return try self.withCString({
+            var statBuffer = stat()
+            if stat($0, &statBuffer) == 0 {
+                return try closure(statBuffer)
+            }
+            if errno == ENOENT {
+                return try closure(nil)
+            }
+            throw FileError.error(errno)
+        })
+    }
+}

+ 8 - 12
XCode/Swifter.xcodeproj/project.pbxproj

@@ -29,9 +29,6 @@
 		7C3196041CC2C68F00DF5406 /* DemoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E81CC2C68F00DF5406 /* DemoServer.swift */; };
 		7C3196051CC2C68F00DF5406 /* DemoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E81CC2C68F00DF5406 /* DemoServer.swift */; };
 		7C3196061CC2C68F00DF5406 /* DemoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E81CC2C68F00DF5406 /* DemoServer.swift */; };
-		7C3196071CC2C68F00DF5406 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E91CC2C68F00DF5406 /* File.swift */; };
-		7C3196081CC2C68F00DF5406 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E91CC2C68F00DF5406 /* File.swift */; };
-		7C3196091CC2C68F00DF5406 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E91CC2C68F00DF5406 /* File.swift */; };
 		7C31960A1CC2C68F00DF5406 /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195EA1CC2C68F00DF5406 /* Files.swift */; };
 		7C31960B1CC2C68F00DF5406 /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195EA1CC2C68F00DF5406 /* Files.swift */; };
 		7C31960C1CC2C68F00DF5406 /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195EA1CC2C68F00DF5406 /* Files.swift */; };
@@ -78,6 +75,9 @@
 		7C3945651D256FDA003EEABA /* Scopes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3945631D256FDA003EEABA /* Scopes.swift */; };
 		7C4785E91C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */; };
 		7C4785EA1C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */; };
+		7C5533191D64F35600094FF6 /* String+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5533181D64F35600094FF6 /* String+File.swift */; };
+		7C55331A1D64F35600094FF6 /* String+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5533181D64F35600094FF6 /* String+File.swift */; };
+		7C55331B1D64F35600094FF6 /* String+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5533181D64F35600094FF6 /* String+File.swift */; };
 		7C5915221C92A99300D884BC /* SwifterTestsReflection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */; };
 		7C5915231C92A99300D884BC /* SwifterTestsReflection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */; };
 		7C5CFD921D5E353D001E1016 /* Socket+TLS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5CFD911D5E353D001E1016 /* Socket+TLS.swift */; };
@@ -97,7 +97,6 @@
 		7C5F79111D56287000C514AA /* Socket+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5F790E1D56287000C514AA /* Socket+File.swift */; };
 		7C615E721D63BE7F0082E4BC /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E71CC2C68F00DF5406 /* App.swift */; };
 		7C615E731D63BE7F0082E4BC /* DemoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E81CC2C68F00DF5406 /* DemoServer.swift */; };
-		7C615E741D63BE7F0082E4BC /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E91CC2C68F00DF5406 /* File.swift */; };
 		7C615E751D63BE7F0082E4BC /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195EA1CC2C68F00DF5406 /* Files.swift */; };
 		7C615E761D63BE7F0082E4BC /* Scopes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3945631D256FDA003EEABA /* Scopes.swift */; };
 		7C615E771D63BE7F0082E4BC /* WebSockets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195EB1CC2C68F00DF5406 /* WebSockets.swift */; };
@@ -117,7 +116,6 @@
 		7C615E851D63BE7F0082E4BC /* String+Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195F91CC2C68F00DF5406 /* String+Misc.swift */; };
 		7C615E941D63BE810082E4BC /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E71CC2C68F00DF5406 /* App.swift */; };
 		7C615E951D63BE810082E4BC /* DemoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E81CC2C68F00DF5406 /* DemoServer.swift */; };
-		7C615E961D63BE810082E4BC /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195E91CC2C68F00DF5406 /* File.swift */; };
 		7C615E971D63BE810082E4BC /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195EA1CC2C68F00DF5406 /* Files.swift */; };
 		7C615E981D63BE810082E4BC /* Scopes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3945631D256FDA003EEABA /* Scopes.swift */; };
 		7C615E991D63BE810082E4BC /* WebSockets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3195EB1CC2C68F00DF5406 /* WebSockets.swift */; };
@@ -283,7 +281,6 @@
 		7C3195E51CC2C68F00DF5406 /* sqlite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite.c; sourceTree = "<group>"; };
 		7C3195E71CC2C68F00DF5406 /* App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
 		7C3195E81CC2C68F00DF5406 /* DemoServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DemoServer.swift; sourceTree = "<group>"; };
-		7C3195E91CC2C68F00DF5406 /* File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
 		7C3195EA1CC2C68F00DF5406 /* Files.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Files.swift; sourceTree = "<group>"; };
 		7C3195EB1CC2C68F00DF5406 /* WebSockets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebSockets.swift; sourceTree = "<group>"; };
 		7C3195ED1CC2C68F00DF5406 /* HttpParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpParser.swift; sourceTree = "<group>"; };
@@ -300,6 +297,7 @@
 		7C3195F91CC2C68F00DF5406 /* String+Misc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Misc.swift"; sourceTree = "<group>"; };
 		7C3945631D256FDA003EEABA /* Scopes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scopes.swift; sourceTree = "<group>"; };
 		7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsWebSocketSession.swift; sourceTree = "<group>"; };
+		7C5533181D64F35600094FF6 /* String+File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+File.swift"; sourceTree = "<group>"; };
 		7C5915211C92A99300D884BC /* SwifterTestsReflection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsReflection.swift; sourceTree = "<group>"; };
 		7C5CFD911D5E353D001E1016 /* Socket+TLS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Socket+TLS.swift"; sourceTree = "<group>"; };
 		7C5F78EE1D54BB5600C514AA /* SwifterTestsAES128.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsAES128.swift; sourceTree = "<group>"; };
@@ -461,7 +459,6 @@
 			children = (
 				7C3195E71CC2C68F00DF5406 /* App.swift */,
 				7C3195E81CC2C68F00DF5406 /* DemoServer.swift */,
-				7C3195E91CC2C68F00DF5406 /* File.swift */,
 				7C3195EA1CC2C68F00DF5406 /* Files.swift */,
 				7C3945631D256FDA003EEABA /* Scopes.swift */,
 				7C3195EB1CC2C68F00DF5406 /* WebSockets.swift */,
@@ -477,6 +474,7 @@
 				7C5F79061D5627EE00C514AA /* Socket+Server.swift */,
 				7C5F790E1D56287000C514AA /* Socket+File.swift */,
 				7C3195F71CC2C68F00DF5406 /* SQLite.swift */,
+				7C5533181D64F35600094FF6 /* String+File.swift */,
 				7C3195F81CC2C68F00DF5406 /* String+BASE64.swift */,
 				7C3195F91CC2C68F00DF5406 /* String+Misc.swift */,
 				7C2C85901D50D83D00B32145 /* JSON.swift */,
@@ -949,7 +947,6 @@
 				7C3196311CC2C68F00DF5406 /* SQLite.swift in Sources */,
 				7C3196341CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
 				7C31961C1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
-				7C3196071CC2C68F00DF5406 /* File.swift in Sources */,
 				7CDF26E51D5CD64600666F69 /* AES128.swift in Sources */,
 				7CDF26F11D5CD64600666F69 /* MD5.swift in Sources */,
 				7CECB5931D5F27040039A704 /* DER.swift in Sources */,
@@ -960,6 +957,7 @@
 				7CDF26FD1D5CD64600666F69 /* SHA1.swift in Sources */,
 				7C3196161CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79071D5627EE00C514AA /* Socket+Server.swift in Sources */,
+				7C5533191D64F35600094FF6 /* String+File.swift in Sources */,
 				7C3196221CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C31960A1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7C3196011CC2C68F00DF5406 /* App.swift in Sources */,
@@ -989,7 +987,6 @@
 				7C3196321CC2C68F00DF5406 /* SQLite.swift in Sources */,
 				7C3196351CC2C68F00DF5406 /* String+BASE64.swift in Sources */,
 				7C31961D1CC2C68F00DF5406 /* HttpRouter.swift in Sources */,
-				7C3196081CC2C68F00DF5406 /* File.swift in Sources */,
 				7CDF26E61D5CD64600666F69 /* AES128.swift in Sources */,
 				7CDF26F21D5CD64600666F69 /* MD5.swift in Sources */,
 				7CECB5941D5F27040039A704 /* DER.swift in Sources */,
@@ -1000,6 +997,7 @@
 				7CDF26FE1D5CD64600666F69 /* SHA1.swift in Sources */,
 				7C3196171CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79081D5627EE00C514AA /* Socket+Server.swift in Sources */,
+				7C55331A1D64F35600094FF6 /* String+File.swift in Sources */,
 				7C3196231CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C31960B1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7C3196021CC2C68F00DF5406 /* App.swift in Sources */,
@@ -1059,13 +1057,13 @@
 				7CDF26E71D5CD64600666F69 /* AES128.swift in Sources */,
 				7CDF26F31D5CD64600666F69 /* MD5.swift in Sources */,
 				7CECB5951D5F27040039A704 /* DER.swift in Sources */,
-				7C3196091CC2C68F00DF5406 /* File.swift in Sources */,
 				7C3196061CC2C68F00DF5406 /* DemoServer.swift in Sources */,
 				7C31962A1CC2C68F00DF5406 /* Reflection.swift in Sources */,
 				7C5CFD941D5E353D001E1016 /* Socket+TLS.swift in Sources */,
 				7CDF26FF1D5CD64600666F69 /* SHA1.swift in Sources */,
 				7C3196181CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79091D5627EE00C514AA /* Socket+Server.swift in Sources */,
+				7C55331B1D64F35600094FF6 /* String+File.swift in Sources */,
 				7C3196241CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
 				7C31960C1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7C3196031CC2C68F00DF5406 /* App.swift in Sources */,
@@ -1115,7 +1113,6 @@
 				7CE425EB1D64A4F900CCD71A /* HEX.swift in Sources */,
 				7C615E751D63BE7F0082E4BC /* Files.swift in Sources */,
 				7C615E731D63BE7F0082E4BC /* DemoServer.swift in Sources */,
-				7C615E741D63BE7F0082E4BC /* File.swift in Sources */,
 				7C615E771D63BE7F0082E4BC /* WebSockets.swift in Sources */,
 				7C615E851D63BE7F0082E4BC /* String+Misc.swift in Sources */,
 				7C4785E91C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */,
@@ -1167,7 +1164,6 @@
 				7CE425EC1D64A4F900CCD71A /* HEX.swift in Sources */,
 				7C615E971D63BE810082E4BC /* Files.swift in Sources */,
 				7C615E951D63BE810082E4BC /* DemoServer.swift in Sources */,
-				7C615E961D63BE810082E4BC /* File.swift in Sources */,
 				7C615E991D63BE810082E4BC /* WebSockets.swift in Sources */,
 				7C615EA71D63BE810082E4BC /* String+Misc.swift in Sources */,
 				7C4785EA1C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */,