From 0e0d47b6ed3e00d16a04abb762d5e279101685fb Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 12 Sep 2015 17:04:34 -0400 Subject: [PATCH] Refactor engine polling. Change SocketGenericParser to SocketStringReader --- .../project.pbxproj | 24 +++---- SocketIO-iOSTests/SocketParserTest.swift | 9 +-- SocketIOClientSwift/SocketEngine.swift | 64 ++++--------------- SocketIOClientSwift/SocketGenericParser.swift | 52 --------------- SocketIOClientSwift/SocketPacket.swift | 3 +- SocketIOClientSwift/SocketParser.swift | 24 +++---- SocketIOClientSwift/SocketStringReader.swift | 57 +++++++++++++++++ 7 files changed, 102 insertions(+), 131 deletions(-) delete mode 100644 SocketIOClientSwift/SocketGenericParser.swift create mode 100644 SocketIOClientSwift/SocketStringReader.swift diff --git a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj index fd6adc5..e7468e6 100644 --- a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj +++ b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj @@ -12,7 +12,7 @@ 572EF23D1B51F18A00EEBB58 /* SocketIO-Mac.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */; settings = {ATTRIBUTES = (Public, ); }; }; 572EF2431B51F18A00EEBB58 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 572EF2381B51F18A00EEBB58 /* SocketIO.framework */; }; 572EF24A1B51F18A00EEBB58 /* SocketIO_MacTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572EF2491B51F18A00EEBB58 /* SocketIO_MacTests.swift */; }; - 57425F9C1BA3A46000BDAAC1 /* SocketGenericParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketGenericParser.swift */; }; + 57425F9C1BA3A46000BDAAC1 /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketStringReader.swift */; }; 57425F9D1BA3A46000BDAAC1 /* SocketEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7E1B51F254004FF46E /* SocketEngine.swift */; }; 57425F9E1BA3A46000BDAAC1 /* SocketParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF851B51F254004FF46E /* SocketParser.swift */; }; 57425F9F1BA3A46000BDAAC1 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF861B51F254004FF46E /* SocketTypes.swift */; }; @@ -28,7 +28,7 @@ 57425FA91BA3A46000BDAAC1 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7C1B51F254004FF46E /* SocketAckManager.swift */; }; 57425FAA1BA3A46000BDAAC1 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF871B51F254004FF46E /* SwiftRegex.swift */; }; 57425FAD1BA3A46000BDAAC1 /* SocketIO-iOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF21E1B51F16C00EEBB58 /* SocketIO-iOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 57425FDC1BA3A4F100BDAAC1 /* SocketGenericParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketGenericParser.swift */; }; + 57425FDC1BA3A4F100BDAAC1 /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketStringReader.swift */; }; 57425FDD1BA3A4F100BDAAC1 /* SocketParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF851B51F254004FF46E /* SocketParser.swift */; }; 57425FDE1BA3A4F100BDAAC1 /* SocketPacket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF841B51F254004FF46E /* SocketPacket.swift */; }; 57425FDF1BA3A4F100BDAAC1 /* SocketFixUTF8.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF811B51F254004FF46E /* SocketFixUTF8.swift */; }; @@ -83,9 +83,9 @@ 74781D5B1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; }; 74781D5C1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; }; 74781D5D1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; }; - 74D765621B9F0D870028551C /* SocketGenericParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketGenericParser.swift */; }; - 74D765631B9F0D9F0028551C /* SocketGenericParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketGenericParser.swift */; }; - 74D765641B9F0DA40028551C /* SocketGenericParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketGenericParser.swift */; }; + 74D765621B9F0D870028551C /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketStringReader.swift */; }; + 74D765631B9F0D9F0028551C /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketStringReader.swift */; }; + 74D765641B9F0DA40028551C /* SocketStringReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D765611B9F0D870028551C /* SocketStringReader.swift */; }; 941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941A4AB91B67A56C00C42318 /* TestKind.swift */; }; 94242BB81B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */; }; 945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7C1B51F254004FF46E /* SocketAckManager.swift */; }; @@ -162,7 +162,7 @@ 5764DF871B51F254004FF46E /* SwiftRegex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftRegex.swift; path = SocketIOClientSwift/SwiftRegex.swift; sourceTree = ""; }; 5764DF881B51F254004FF46E /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = SocketIOClientSwift/WebSocket.swift; sourceTree = ""; }; 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketIOClientStatus.swift; path = SocketIOClientSwift/SocketIOClientStatus.swift; sourceTree = ""; }; - 74D765611B9F0D870028551C /* SocketGenericParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SocketGenericParser.swift; path = SocketIOClientSwift/SocketGenericParser.swift; sourceTree = ""; }; + 74D765611B9F0D870028551C /* SocketStringReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SocketStringReader.swift; path = SocketIOClientSwift/SocketStringReader.swift; sourceTree = ""; }; 941A4AB91B67A56C00C42318 /* TestKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestKind.swift; sourceTree = ""; }; 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespaceAcknowledgementTest.swift; sourceTree = ""; }; 945B65421B63D9DB0081E995 /* SocketEmitTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEmitTest.swift; sourceTree = ""; }; @@ -333,12 +333,12 @@ 5764DF7F1B51F254004FF46E /* SocketEngineClient.swift */, 5764DF801B51F254004FF46E /* SocketEventHandler.swift */, 5764DF811B51F254004FF46E /* SocketFixUTF8.swift */, - 74D765611B9F0D870028551C /* SocketGenericParser.swift */, 5764DF821B51F254004FF46E /* SocketIOClient.swift */, 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */, 5764DF831B51F254004FF46E /* SocketLogger.swift */, 5764DF841B51F254004FF46E /* SocketPacket.swift */, 5764DF851B51F254004FF46E /* SocketParser.swift */, + 74D765611B9F0D870028551C /* SocketStringReader.swift */, 5764DF861B51F254004FF46E /* SocketTypes.swift */, 5764DF871B51F254004FF46E /* SwiftRegex.swift */, 5764DF881B51F254004FF46E /* WebSocket.swift */, @@ -579,7 +579,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 74D765631B9F0D9F0028551C /* SocketGenericParser.swift in Sources */, + 74D765631B9F0D9F0028551C /* SocketStringReader.swift in Sources */, 5764DF8D1B51F254004FF46E /* SocketEngine.swift in Sources */, 5764DF9B1B51F254004FF46E /* SocketParser.swift in Sources */, 5764DF9D1B51F254004FF46E /* SocketTypes.swift in Sources */, @@ -601,7 +601,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 74D765621B9F0D870028551C /* SocketGenericParser.swift in Sources */, + 74D765621B9F0D870028551C /* SocketStringReader.swift in Sources */, 945B653E1B5FCEEA0081E995 /* SocketParser.swift in Sources */, 945B653D1B5FCEEA0081E995 /* SocketPacket.swift in Sources */, 945B653A1B5FCEEA0081E995 /* SocketFixUTF8.swift in Sources */, @@ -632,7 +632,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 74D765641B9F0DA40028551C /* SocketGenericParser.swift in Sources */, + 74D765641B9F0DA40028551C /* SocketStringReader.swift in Sources */, 5764DF8E1B51F254004FF46E /* SocketEngine.swift in Sources */, 5764DF9C1B51F254004FF46E /* SocketParser.swift in Sources */, 5764DF9E1B51F254004FF46E /* SocketTypes.swift in Sources */, @@ -663,7 +663,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 57425F9C1BA3A46000BDAAC1 /* SocketGenericParser.swift in Sources */, + 57425F9C1BA3A46000BDAAC1 /* SocketStringReader.swift in Sources */, 57425F9D1BA3A46000BDAAC1 /* SocketEngine.swift in Sources */, 57425F9E1BA3A46000BDAAC1 /* SocketParser.swift in Sources */, 57425F9F1BA3A46000BDAAC1 /* SocketTypes.swift in Sources */, @@ -685,7 +685,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 57425FDC1BA3A4F100BDAAC1 /* SocketGenericParser.swift in Sources */, + 57425FDC1BA3A4F100BDAAC1 /* SocketStringReader.swift in Sources */, 57425FDD1BA3A4F100BDAAC1 /* SocketParser.swift in Sources */, 57425FDE1BA3A4F100BDAAC1 /* SocketPacket.swift in Sources */, 57425FDF1BA3A4F100BDAAC1 /* SocketFixUTF8.swift in Sources */, diff --git a/SocketIO-iOSTests/SocketParserTest.swift b/SocketIO-iOSTests/SocketParserTest.swift index 7198b4c..beab086 100644 --- a/SocketIO-iOSTests/SocketParserTest.swift +++ b/SocketIO-iOSTests/SocketParserTest.swift @@ -72,24 +72,25 @@ class SocketParserTest: XCTestCase { } func testGenericParser() { - var parser = SocketGenericParser(message: "61-/swift,", currentIndex: 0) + var parser = SocketStringReader(message: "61-/swift,", currentIndex: "61-/swift,".startIndex) XCTAssertEqual(parser.read(1), "6") XCTAssertEqual(parser.currentCharacter, "1") XCTAssertEqual(parser.readUntilStringOccurence("-"), "1") - XCTAssertEqual(parser.currentCharacter, "-") + XCTAssertEqual(parser.currentCharacter, "/") } - func validateParseResult(message:String) { + func validateParseResult(message: String) { let validValues = SocketParserTest.packetTypes[message]! let packet = SocketParser.parseString(message) let type = message.substringWithRange(Range(start: message.startIndex, end: message.startIndex.advancedBy(1))) if let packet = packet { + print(packet) XCTAssertEqual(packet.type, SocketPacket.PacketType(str:type)!) XCTAssertEqual(packet.nsp, validValues.0) XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1)) XCTAssertTrue((packet.binary as NSArray).isEqualToArray(validValues.2)) XCTAssertEqual(packet.id, validValues.3) - }else { + } else { XCTFail() } } diff --git a/SocketIOClientSwift/SocketEngine.swift b/SocketIOClientSwift/SocketEngine.swift index cddaaf9..da090c9 100644 --- a/SocketIOClientSwift/SocketEngine.swift +++ b/SocketIOClientSwift/SocketEngine.swift @@ -154,7 +154,6 @@ public final class SocketEngine: NSObject, WebSocketDelegate { } if params != nil { - for (key, value) in params! { let keyEsc = key.stringByAddingPercentEncodingWithAllowedCharacters( allowedCharacterSet)! @@ -350,10 +349,10 @@ public final class SocketEngine: NSObject, WebSocketDelegate { // We had packets waiting for send when we upgraded // Send them raw private func flushWaitingForPostToWebSocket() { - if let ws = ws { - for msg in postWait { - ws.writeString(msg) - } + guard let ws = self.ws else {return} + + for msg in postWait { + ws.writeString(msg) } postWait.removeAll(keepCapacity: true) @@ -486,54 +485,19 @@ public final class SocketEngine: NSObject, WebSocketDelegate { } // Translatation of engine.io-parser#decodePayload - private func parsePollingMessage(str:String) { + private func parsePollingMessage(str: String) { guard str.characters.count != 1 else { return } - // println(str) - - let strArray = Array(str.characters) - var length = "" - var n = 0 - var msg = "" - - func testLength(length: String, inout n: Int) -> Bool { - if let num = Int(length) { - n = num - return false - } else { - return true - } - } - - for var i = 0, l = str.characters.count; i < l; i++ { - let chr = String(strArray[i]) - - if chr != ":" { - length += chr - } else { - if length == "" || testLength(length, n: &n) { - Logger.error("Parsing error: %@", type: logType, args: str) - handlePollingFailed("Error parsing XHR message") - return - } - - msg = String(strArray[i+1...i+n]) - - if let lengthInt = Int(length) where lengthInt != msg.characters.count { - Logger.error("Parsing error: %@", type: logType, args: str) - return - } - - if msg.characters.count != 0 { - // Be sure to capture the value of the msg - dispatch_async(handleQueue) { - self.parseEngineMessage(msg, fromPolling: true) - } - } - - i += n - length = "" + + var reader = SocketStringReader(message: str, currentIndex: str.startIndex) + + while reader.hasNext { + let n = reader.readUntilStringOccurence(":") + let str = reader.read(Int(n)!) + + dispatch_async(handleQueue) { + self.parseEngineMessage(str, fromPolling: true) } } } diff --git a/SocketIOClientSwift/SocketGenericParser.swift b/SocketIOClientSwift/SocketGenericParser.swift deleted file mode 100644 index af50c9a..0000000 --- a/SocketIOClientSwift/SocketGenericParser.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// GenericSocketParser.swift -// Socket.IO-Client-Swift -// -// Created by Lukas Schmidt on 07.09.15. -// -// - -import Foundation - -struct SocketGenericParser { - let message: String - var currentIndex: Int - var messageCharacters: [Character] { - return Array(message.characters) - } - - var currentCharacter: String? { - if currentIndex >= messageCharacters.count { - return nil - } - - return String(messageCharacters[currentIndex]) - } - - mutating func read(characterLength: Int) -> String? { - let startIndex = message.startIndex.advancedBy(currentIndex) - let range = Range(start: startIndex, end: startIndex.advancedBy(characterLength)) - currentIndex = currentIndex + characterLength - - return message.substringWithRange(range) - } - - mutating func readUntilStringOccurence(string: String) -> String? { - let startIndex = message.startIndex.advancedBy(currentIndex) - let range = Range(start: startIndex, end: message.endIndex) - let subString = message.substringWithRange(range) as NSString - let foundRange = subString.rangeOfString(string) - - if foundRange.location == Int.max { - return nil - } - - currentIndex = currentIndex + foundRange.location - - return subString.substringToIndex(foundRange.location) - } - - mutating func readUntilEnd() -> String { - return read(messageCharacters.count - currentIndex)! - } -} \ No newline at end of file diff --git a/SocketIOClientSwift/SocketPacket.swift b/SocketIOClientSwift/SocketPacket.swift index 12b975a..5608d7d 100644 --- a/SocketIOClientSwift/SocketPacket.swift +++ b/SocketIOClientSwift/SocketPacket.swift @@ -64,7 +64,8 @@ struct SocketPacket { var binary: [NSData] var data: [AnyObject] var description: String { - return "SocketPacket {type: \(String(type.rawValue)); data: \(String(data)); id: \(id); placeholders: \(placeholders);}" + return "SocketPacket {type: \(String(type.rawValue)); data: " + + "\(String(data)); id: \(id); placeholders: \(placeholders); nsp: \(nsp)}" } var event: String { diff --git a/SocketIOClientSwift/SocketParser.swift b/SocketIOClientSwift/SocketParser.swift index 1c06328..ec47dbd 100644 --- a/SocketIOClientSwift/SocketParser.swift +++ b/SocketIOClientSwift/SocketParser.swift @@ -59,12 +59,12 @@ class SocketParser { // Translation of socket.io-client#decodeString static func parseString(message: String) -> SocketPacket? { - var parser = SocketGenericParser(message: message, currentIndex: 0) + var parser = SocketStringReader(message: message, currentIndex: message.startIndex) - guard let typeString = parser.read(1), type = SocketPacket.PacketType(str: typeString) + guard let type = SocketPacket.PacketType(str: parser.read(1)) else {return nil} - if parser.messageCharacters.count == 1 { + if !parser.hasNext { return SocketPacket(type: type, nsp: "/") } @@ -72,34 +72,34 @@ class SocketParser { var placeholders = -1 if type == .BinaryEvent || type == .BinaryAck { - if let buffer = parser.readUntilStringOccurence("-"), let holders = Int(buffer) - where parser.read(1)! == "-" { + Logger.log("Got some binary", type: "SocketParser") + if let holders = Int(parser.readUntilStringOccurence("-")) { placeholders = holders } else { return nil } } + if parser.currentCharacter == "/" { namespace = parser.readUntilStringOccurence(",") ?? parser.readUntilEnd() - parser.currentIndex++ } - if parser.currentIndex >= parser.messageCharacters.count { + if !parser.hasNext { return SocketPacket(type: type, id: -1, nsp: namespace ?? "/", placeholders: placeholders) } var idString = "" - while parser.currentIndex < parser.messageCharacters.count { - if let next = parser.read(1), let int = Int(next) { + while parser.hasNext { + if let int = Int(parser.read(1)) { idString += String(int) } else { - parser.currentIndex -= 2 + parser.advanceIndexBy(-2) break } } - let d = message[message.startIndex.advancedBy(parser.currentIndex + 1)...message.startIndex.advancedBy(message.characters.count - 1)] + let d = message[parser.currentIndex.advancedBy(1)...message.endIndex.predecessor()] let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" let data = parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders] @@ -126,7 +126,7 @@ class SocketParser { Logger.log("Parsing %@", type: "SocketParser", args: message) guard let pack = parseString(message) else { - Logger.error("Parsing message", type: "SocketParser", args: message) + Logger.error("Parsing message: %@", type: "SocketParser", args: message) return } diff --git a/SocketIOClientSwift/SocketStringReader.swift b/SocketIOClientSwift/SocketStringReader.swift new file mode 100644 index 0000000..9450461 --- /dev/null +++ b/SocketIOClientSwift/SocketStringReader.swift @@ -0,0 +1,57 @@ +// +// SocketStringReader.swift +// Socket.IO-Client-Swift +// +// Created by Lukas Schmidt on 07.09.15. +// +// + +import Foundation + +struct SocketStringReader { + let message: String + var currentIndex: String.Index + var hasNext: Bool { + return currentIndex != message.endIndex + } + + var messageCharacters: [Character] { + return Array(message.characters) + } + + var currentCharacter: String { + return String(message[currentIndex]) + } + + mutating func advanceIndexBy(n: Int) { + currentIndex = currentIndex.advancedBy(n) + } + + mutating func read(readLength: Int) -> String { + let range = Range(start: currentIndex, end: currentIndex.advancedBy(readLength)) + advanceIndexBy(readLength) + + return message.substringWithRange(range) + } + + mutating func readUntilStringOccurence(string: String) -> String { + let range = Range(start: currentIndex, end: message.endIndex) + let subString = message.substringWithRange(range) as NSString + let foundRange = subString.rangeOfString(string) + + if foundRange.length == 0 { + let restOfString = message[currentIndex...message.endIndex.predecessor()] + currentIndex = message.endIndex + + return restOfString + } + + advanceIndexBy(foundRange.location + 1) + + return subString.substringToIndex(foundRange.location) + } + + mutating func readUntilEnd() -> String { + return read(currentIndex.distanceTo(message.endIndex)) + } +} \ No newline at end of file