Procházet zdrojové kódy

Removed stringByTrimmingCharactersInSet dependency from HttpParser ( Linux support ).
Removed componentsSeparatedByString dependency from HttpParser ( Linux support ).

Damian Kołakowski před 10 roky
rodič
revize
e5a98d3251

+ 8 - 11
Sources/Swifter/HttpParser.swift

@@ -16,7 +16,7 @@ class HttpParser {
     
     func readHttpRequest(socket: Socket) throws -> HttpRequest {
         let statusLine = try socket.readLine()
-        let statusLineTokens = statusLine.componentsSeparatedByString(" ")
+        let statusLineTokens = statusLine.componentsSeparatedBy(" ")
         print(statusLineTokens)
         if statusLineTokens.count < 3 {
             throw HttpParserError.InvalidStatusLine(statusLine)
@@ -33,18 +33,15 @@ class HttpParser {
     }
     
     private func extractUrlParams(url: String) -> [(String, String)] {
-        guard let query = url.componentsSeparatedByString("?").last else {
+        guard let query = url.componentsSeparatedBy("?").last else {
             return []
         }
-        return query.componentsSeparatedByString("&").map { (param:String) -> (String, String) in
-            let tokens = param.componentsSeparatedByString("=")
+        return query.componentsSeparatedBy("&").map { (param:String) -> (String, String) in
+            let tokens = param.componentsSeparatedBy("=")
             guard tokens.count >= 2 else {
                 return ("", "")
             }
-            guard let k = tokens[0].stringByRemovingPercentEncoding, v = tokens[1].stringByRemovingPercentEncoding else {
-                return ("", "")
-            }
-            return (k, v)
+            return (tokens[0].stringByRemovingPercent(), tokens[1].stringByRemovingPercent())
         }
     }
     
@@ -69,13 +66,13 @@ class HttpParser {
             if headerLine.isEmpty {
                 return requestHeaders
             }
-            let headerTokens = headerLine.componentsSeparatedByString(":")
+            let headerTokens = headerLine.componentsSeparatedBy(":")
             if headerTokens.count >= 2 {
                 // RFC 2616 - "Hypertext Transfer Protocol -- HTTP/1.1", paragraph 4.2, "Message Headers":
                 // "Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive."
                 // We will keep lower case version.
                 let headerName = headerTokens[0].lowercaseString
-                let headerValue = headerTokens[1].stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
+                let headerValue = headerTokens[1].trim()
                 if !headerName.isEmpty && !headerValue.isEmpty {
                     requestHeaders.updateValue(headerValue, forKey: headerName)
                 }
@@ -85,7 +82,7 @@ class HttpParser {
     
     func supportsKeepAlive(headers: [String: String]) -> Bool {
         if let value = headers["connection"] {
-            return "keep-alive" == value.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).lowercaseString
+            return "keep-alive" == value.trim()
         }
         return false
     }

+ 1 - 1
Sources/Swifter/HttpRequest.swift

@@ -18,7 +18,7 @@ public struct HttpRequest {
     
     public func parseForm() -> [(String, String)] {
         if let body = body {
-            return body.componentsSeparatedByString("&").map { (param:String) -> (String, String) in
+            return body.componentsSeparatedBy("&").map { (param:String) -> (String, String) in
                 let tokens = param.componentsSeparatedByString("=")
                 if tokens.count >= 2 {
                     let key = tokens[0].stringByReplacingOccurrencesOfString("+", withString: " ").stringByRemovingPercentEncoding

+ 74 - 0
Sources/Swifter/String+Misc.swift

@@ -0,0 +1,74 @@
+//
+//  String+Linux.swift
+//  Swifter
+//  Copyright (c) 2014 Damian Kołakowski. All rights reserved.
+//
+
+extension String {
+
+    public func componentsSeparatedBy(separator: Character) -> [String] {
+        return self.characters.split { $0 == separator }.map(String.init)
+    }
+    
+    public func trim() -> String {
+        var scalars = self.unicodeScalars
+        while let _ = unicodeScalarToUInt32Whitespace(scalars.first) { scalars.removeFirst() }
+        while let _ = unicodeScalarToUInt32Whitespace(scalars.last) { scalars.removeLast() }
+        return String(scalars)
+    }
+    
+    public func stringByRemovingPercent() -> String {
+        var scalars = self.unicodeScalars
+        var buffer = [Character]()
+        while let scalar = scalars.popFirst() {
+            guard scalar.isASCII() else {
+                buffer.append(Character(scalar))
+                continue
+            }
+            if ( scalar == "%" ) {
+                let first = scalars.popFirst()
+                let secon = scalars.popFirst()
+                if let first = unicodeScalarToUInt32Hex(first), secon = unicodeScalarToUInt32Hex(secon) {
+                    buffer.append(Character(UnicodeScalar(first*16+secon)))
+                } else {
+                    if let first = first {
+                        buffer.append(Character(first))
+                    }
+                    if let secon = secon {
+                        buffer.append(Character(secon))
+                    }
+                }
+            } else {
+                buffer.append(Character(scalar))
+            }
+        }
+        return String(buffer)
+    }
+    
+    private func unicodeScalarToUInt32Whitespace(x: UnicodeScalar?) -> UInt32? {
+        if let x = x {
+            if (x.value >= 9 && x.value <= 13) {
+                return x.value;
+            }
+            if (x.value == 32) {
+                return x.value;
+            }
+        }
+        return nil
+    }
+    
+    private func unicodeScalarToUInt32Hex(x: UnicodeScalar?) -> UInt32? {
+        if let x = x {
+            if (x.value >= 48 && x.value <= 57) {
+                return x.value - 48
+            }
+            if (x.value >= 97 && x.value <= 102) {
+                return x.value - 97
+            }
+            if (x.value >= 65 && x.value <= 70) {
+                return x.value - 65
+            }
+        }
+        return nil
+    }
+}

+ 10 - 0
Swifter.xcodeproj/project.pbxproj

@@ -17,6 +17,10 @@
 		7CA4815819A2EF2B0030B30D /* test.json in Resources */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CA4815919A2EF560030B30D /* test.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7CA4815719A2EF2B0030B30D /* test.json */; };
 		7CB102E01A17381D00CBA3B4 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 7CB102DF1A17381D00CBA3B4 /* logo.png */; };
+		7CD6DAB91C15C48500A04931 /* String+Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CD6DAB81C15C48500A04931 /* String+Misc.swift */; };
+		7CD6DABA1C15C48500A04931 /* String+Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CD6DAB81C15C48500A04931 /* String+Misc.swift */; };
+		7CD6DABB1C15C48500A04931 /* String+Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CD6DAB81C15C48500A04931 /* String+Misc.swift */; };
+		7CD6DABC1C15C48500A04931 /* String+Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CD6DAB81C15C48500A04931 /* String+Misc.swift */; };
 		7CDAB8121BE2A1D400C8A977 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDAB80C1BE2A1D400C8A977 /* AppDelegate.swift */; };
 		7CDAB8131BE2A1D400C8A977 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80D1BE2A1D400C8A977 /* Main.storyboard */; };
 		7CDAB8141BE2A1D400C8A977 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */; };
@@ -98,6 +102,7 @@
 		7CA4813D19A2EA8D0030B30D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
 		7CA4815719A2EF2B0030B30D /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = "<group>"; };
 		7CB102DF1A17381D00CBA3B4 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = "<group>"; };
+		7CD6DAB81C15C48500A04931 /* String+Misc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Misc.swift"; sourceTree = "<group>"; };
 		7CDAB80C1BE2A1D400C8A977 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		7CDAB80E1BE2A1D400C8A977 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
 		7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
@@ -239,6 +244,7 @@
 				7CEAF8501C14B29B003252DE /* HttpResponse.swift */,
 				7CEAF8511C14B29B003252DE /* HttpServer.swift */,
 				7CEAF8521C14B29B003252DE /* Socket.swift */,
+				7CD6DAB81C15C48500A04931 /* String+Misc.swift */,
 			);
 			path = Swifter;
 			sourceTree = "<group>";
@@ -424,6 +430,7 @@
 				7CEAF8611C14B29B003252DE /* HttpRequest.swift in Sources */,
 				7CEAF85D1C14B29B003252DE /* HttpParser.swift in Sources */,
 				7CEAF8551C14B29B003252DE /* DemoServer.swift in Sources */,
+				7CD6DABB1C15C48500A04931 /* String+Misc.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -438,6 +445,7 @@
 				7CEAF8621C14B29B003252DE /* HttpRequest.swift in Sources */,
 				7CEAF85E1C14B29B003252DE /* HttpParser.swift in Sources */,
 				7CEAF8561C14B29B003252DE /* DemoServer.swift in Sources */,
+				7CD6DABC1C15C48500A04931 /* String+Misc.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -448,6 +456,7 @@
 				7CDAB8161BE2A1D400C8A977 /* ViewController.swift in Sources */,
 				7CEAF8531C14B29B003252DE /* DemoServer.swift in Sources */,
 				7CEAF8671C14B29B003252DE /* HttpServer.swift in Sources */,
+				7CD6DAB91C15C48500A04931 /* String+Misc.swift in Sources */,
 				7CEAF8571C14B29B003252DE /* HttpHandlers.swift in Sources */,
 				7CEAF85B1C14B29B003252DE /* HttpParser.swift in Sources */,
 				7CEAF86B1C14B29B003252DE /* Socket.swift in Sources */,
@@ -464,6 +473,7 @@
 				7CA4813E19A2EA8D0030B30D /* main.swift in Sources */,
 				7CEAF8541C14B29B003252DE /* DemoServer.swift in Sources */,
 				7CEAF8681C14B29B003252DE /* HttpServer.swift in Sources */,
+				7CD6DABA1C15C48500A04931 /* String+Misc.swift in Sources */,
 				7CEAF8581C14B29B003252DE /* HttpHandlers.swift in Sources */,
 				7CEAF85C1C14B29B003252DE /* HttpParser.swift in Sources */,
 				7CEAF86C1C14B29B003252DE /* Socket.swift in Sources */,

binární
Swifter.xcodeproj/project.xcworkspace/xcuserdata/damiankolakowski.xcuserdatad/UserInterfaceState.xcuserstate


+ 32 - 0
Swifter.xcodeproj/xcuserdata/damiankolakowski.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -782,5 +782,37 @@
             landmarkType = "5">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Sources/Swifter/String+Misc.swift"
+            timestampString = "471207427.521354"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "29"
+            endingLineNumber = "29"
+            landmarkName = "stringByRemovingPercent()"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "No"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            filePath = "Sources/Swifter/String+Misc.swift"
+            timestampString = "471207463.1494"
+            startingColumnNumber = "9223372036854775807"
+            endingColumnNumber = "9223372036854775807"
+            startingLineNumber = "14"
+            endingLineNumber = "14"
+            landmarkName = "trim()"
+            landmarkType = "5">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>