From 6d125d2093883502d18692b8bffff6d5384a809e Mon Sep 17 00:00:00 2001 From: Ian Gray Date: Sat, 16 Dec 2023 00:59:39 +0000 Subject: [PATCH] Remove submodules, add Starscream and SwiftyJson as Swift Package Manager deps. New Starscream has a pile of breaking changes that needed handling. --- .gitmodules | 3 - .../Quiz Server.xcodeproj/project.pbxproj | 127 +- .../contents.xcworkspacedata | 2 +- .../xcshareddata/swiftpm/Package.resolved | 23 + .../ControllerWindowController.swift | 50 +- Quiz Server/Quiz Server/LEDWebSocket.swift | 5 +- Quiz Server/SwiftyJSON/SwiftyJSON.swift | 1440 ----------------- Starscream | 1 - 8 files changed, 113 insertions(+), 1538 deletions(-) create mode 100644 Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved delete mode 100644 Quiz Server/SwiftyJSON/SwiftyJSON.swift delete mode 160000 Starscream diff --git a/.gitmodules b/.gitmodules index c40b3cc..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "Starscream"] - path = Starscream - url = https://github.com/daltoniam/Starscream.git diff --git a/Quiz Server/Quiz Server.xcodeproj/project.pbxproj b/Quiz Server/Quiz Server.xcodeproj/project.pbxproj index 802b54b..3eb4185 100644 --- a/Quiz Server/Quiz Server.xcodeproj/project.pbxproj +++ b/Quiz Server/Quiz Server.xcodeproj/project.pbxproj @@ -17,6 +17,8 @@ 3C708BF71A379EE1007E24F5 /* buzzer.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3C708BF61A379EE1007E24F5 /* buzzer.wav */; }; 3C77C8A31DEF69E10088B36A /* location.sks in Resources */ = {isa = PBXBuildFile; fileRef = 3C77C8A11DEF69E10088B36A /* location.sks */; }; 3C77C8A41DEF69E10088B36A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3C77C8A21DEF69E10088B36A /* Assets.xcassets */; }; + 3C78068A2B2D1F83007D58AE /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = 3C7806892B2D1F83007D58AE /* Starscream */; }; + 3C78068D2B2D2D18007D58AE /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 3C78068C2B2D2D18007D58AE /* SwiftyJSON */; }; 3C7F5E591DF454AA008075B8 /* locationstar.sks in Resources */ = {isa = PBXBuildFile; fileRef = 3C7F5E581DF454AA008075B8 /* locationstar.sks */; }; 3C8517E42B2243A000BBCABA /* quietbuzz1.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3C8517E12B22439F00BBCABA /* quietbuzz1.mp3 */; }; 3C8517E52B2243A000BBCABA /* quietbuzz2.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3C8517E32B22439F00BBCABA /* quietbuzz2.mp3 */; }; @@ -25,8 +27,6 @@ 3C872EB21C03D35100A2B397 /* tick.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3C872EB11C03D35100A2B397 /* tick.mp3 */; }; 3C872EB41C03D47A00A2B397 /* blop.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3C872EB31C03D47A00A2B397 /* blop.mp3 */; }; 3C872EB61C03D53000A2B397 /* airhorn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3C872EB51C03D53000A2B397 /* airhorn.mp3 */; }; - 3C8DD5191FB89672007DA61F /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C6C3C681FB2140B0096D530 /* Starscream.framework */; }; - 3C8DD51A1FB89679007DA61F /* Starscream.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3C6C3C681FB2140B0096D530 /* Starscream.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3C934627237DAEED009DBD0C /* altBuzz1.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3C934626237DAEED009DBD0C /* altBuzz1.wav */; }; 3C934629237DB637009DBD0C /* altBuzz2.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3C934628237DB637009DBD0C /* altBuzz2.wav */; }; 3C93462B237DB6B0009DBD0C /* altBuzz3.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3C93462A237DB6B0009DBD0C /* altBuzz3.wav */; }; @@ -75,7 +75,6 @@ 46B025BA1A1C0FE10088294B /* ControllerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46B025B81A1C0FE10088294B /* ControllerWindowController.swift */; }; 46B025BB1A1C0FE10088294B /* ControllerWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 46B025B91A1C0FE10088294B /* ControllerWindow.xib */; }; 46BBC4541DF0768600C41112 /* EHSMB.TTF in CopyFiles */ = {isa = PBXBuildFile; fileRef = 46BBC4461DF0725600C41112 /* EHSMB.TTF */; }; - 46BBC4581DF383F400C41112 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46BBC4571DF383F400C41112 /* SwiftyJSON.swift */; }; 46BBC4611DF39AA000C41112 /* Boggle.plist in Resources */ = {isa = PBXBuildFile; fileRef = 46BBC4601DF39AA000C41112 /* Boggle.plist */; }; 46BBD3CD21B83DED0010319E /* ClockNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46BBD3CC21B83DED0010319E /* ClockNode.swift */; }; 46C132B0239EA626004AFAA2 /* AnniversaryNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C132AF239EA626004AFAA2 /* AnniversaryNode.swift */; }; @@ -86,30 +85,6 @@ 46F9A1281BFA8D88003E4023 /* IdleScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F9A1271BFA8D88003E4023 /* IdleScene.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 3C6C3C671FB2140B0096D530 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3CD1765C1DDB4AA900F54D47 /* Starscream.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 33CCF0921F5DDC030099B092; - remoteInfo = Starscream; - }; - 3C6C3C691FB2140B0096D530 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3CD1765C1DDB4AA900F54D47 /* Starscream.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 335FA2021F5DF71D00F6D2EC; - remoteInfo = "Starscream Tests"; - }; - 3C8DD5151FB8966A007DA61F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3CD1765C1DDB4AA900F54D47 /* Starscream.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 33CCF0841F5DDC030099B092; - remoteInfo = Starscream; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 46B025701A1BF4ED0088294B /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -117,7 +92,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3C8DD51A1FB89679007DA61F /* Starscream.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -162,7 +136,6 @@ 3C971C8E2396A50E000346A7 /* emojsplosion.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = emojsplosion.sks; sourceTree = ""; }; 3CC339F92B277C95000D8CCE /* TrueFalseScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrueFalseScene.swift; sourceTree = ""; }; 3CC862822B138BDC0060A7E0 /* drums.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = drums.wav; sourceTree = ""; }; - 3CD1765C1DDB4AA900F54D47 /* Starscream.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Starscream.xcodeproj; path = ../Starscream/Starscream.xcodeproj; sourceTree = ""; }; 3CD1DF541A306820003DEA9F /* counter_wrong.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = counter_wrong.wav; sourceTree = ""; }; 3CD1DF551A306820003DEA9F /* counter_score100.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = counter_score100.wav; sourceTree = ""; }; 3CD1DF561A306820003DEA9F /* counter_soft_end.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = counter_soft_end.wav; sourceTree = ""; }; @@ -208,7 +181,6 @@ 46B025B81A1C0FE10088294B /* ControllerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControllerWindowController.swift; sourceTree = ""; }; 46B025B91A1C0FE10088294B /* ControllerWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ControllerWindow.xib; sourceTree = ""; }; 46BBC4461DF0725600C41112 /* EHSMB.TTF */ = {isa = PBXFileReference; lastKnownFileType = file; path = EHSMB.TTF; sourceTree = ""; }; - 46BBC4571DF383F400C41112 /* SwiftyJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyJSON.swift; sourceTree = ""; }; 46BBC4601DF39AA000C41112 /* Boggle.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Boggle.plist; sourceTree = ""; }; 46BBD3CC21B83DED0010319E /* ClockNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClockNode.swift; sourceTree = ""; }; 46BBD3D021B847980010319E /* Clock.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Clock.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; @@ -225,10 +197,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3C8DD5191FB89672007DA61F /* Starscream.framework in Frameworks */, 46596C801A38DE5900822FB7 /* SpriteKit.framework in Frameworks */, 3CD1DF631A3069CC003DEA9F /* QuartzCore.framework in Frameworks */, 46B0254B1A1BF04D0088294B /* IOKit.framework in Frameworks */, + 3C78068D2B2D2D18007D58AE /* SwiftyJSON in Frameworks */, + 3C78068A2B2D1F83007D58AE /* Starscream in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -283,20 +256,9 @@ name = "SpriteKit Scenes"; sourceTree = ""; }; - 3CD1765D1DDB4AA900F54D47 /* Products */ = { - isa = PBXGroup; - children = ( - 3C6C3C681FB2140B0096D530 /* Starscream.framework */, - 3C6C3C6A1FB2140B0096D530 /* Starscream Tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; 46056EAB1A19624E00C37628 = { isa = PBXGroup; children = ( - 3CD1765C1DDB4AA900F54D47 /* Starscream.xcodeproj */, - 46BBC4561DF383F400C41112 /* SwiftyJSON */, 46B0254C1A1BF0590088294B /* Frameworks */, 46056EB61A19624E00C37628 /* Quiz Server */, 46056EB51A19624E00C37628 /* Products */, @@ -377,14 +339,6 @@ name = Frameworks; sourceTree = ""; }; - 46BBC4561DF383F400C41112 /* SwiftyJSON */ = { - isa = PBXGroup; - children = ( - 46BBC4571DF383F400C41112 /* SwiftyJSON.swift */, - ); - path = SwiftyJSON; - sourceTree = ""; - }; 46BBD3CF21B847980010319E /* Playgrounds */ = { isa = PBXGroup; children = ( @@ -411,9 +365,12 @@ buildRules = ( ); dependencies = ( - 3C8DD5161FB8966A007DA61F /* PBXTargetDependency */, ); name = "Quiz Server"; + packageProductDependencies = ( + 3C7806892B2D1F83007D58AE /* Starscream */, + 3C78068C2B2D2D18007D58AE /* SwiftyJSON */, + ); productName = QuizServer; productReference = 46056EB41A19624E00C37628 /* Quiz Server.app */; productType = "com.apple.product-type.application"; @@ -445,14 +402,12 @@ Base, ); mainGroup = 46056EAB1A19624E00C37628; + packageReferences = ( + 3C7806882B2D1F83007D58AE /* XCRemoteSwiftPackageReference "Starscream" */, + 3C78068B2B2D2D18007D58AE /* XCRemoteSwiftPackageReference "SwiftyJSON" */, + ); productRefGroup = 46056EB51A19624E00C37628 /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 3CD1765D1DDB4AA900F54D47 /* Products */; - ProjectRef = 3CD1765C1DDB4AA900F54D47 /* Starscream.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 46056EB31A19624E00C37628 /* Quiz Server */, @@ -460,23 +415,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 3C6C3C681FB2140B0096D530 /* Starscream.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = Starscream.framework; - remoteRef = 3C6C3C671FB2140B0096D530 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3C6C3C6A1FB2140B0096D530 /* Starscream Tests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = "Starscream Tests.xctest"; - remoteRef = 3C6C3C691FB2140B0096D530 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 46056EB21A19624E00C37628 /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -546,7 +484,6 @@ 466B46D51DEC98E400428CDC /* GeographyScene.swift in Sources */, 46056ED61A1974A800C37628 /* StartupView.swift in Sources */, 3C2543242B123E7D008A3FDB /* LEDWebSocket.swift in Sources */, - 46BBC4581DF383F400C41112 /* SwiftyJSON.swift in Sources */, 46A739391BFAB45300E03DE5 /* BuzzerScene.swift in Sources */, 3C366CBC1FB9F0A2006BA9B1 /* TextScene.swift in Sources */, 46DF9D08239672FF00D019A3 /* MusicScene.swift in Sources */, @@ -566,14 +503,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 3C8DD5161FB8966A007DA61F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Starscream; - targetProxy = 3C8DD5151FB8966A007DA61F /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 46056EBD1A19624E00C37628 /* MainMenu.xib */ = { isa = PBXVariantGroup; @@ -777,6 +706,38 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 3C7806882B2D1F83007D58AE /* XCRemoteSwiftPackageReference "Starscream" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/daltoniam/Starscream.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 4.0.6; + }; + }; + 3C78068B2B2D2D18007D58AE /* XCRemoteSwiftPackageReference "SwiftyJSON" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SwiftyJSON/SwiftyJSON.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.0.1; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 3C7806892B2D1F83007D58AE /* Starscream */ = { + isa = XCSwiftPackageProductDependency; + package = 3C7806882B2D1F83007D58AE /* XCRemoteSwiftPackageReference "Starscream" */; + productName = Starscream; + }; + 3C78068C2B2D2D18007D58AE /* SwiftyJSON */ = { + isa = XCSwiftPackageProductDependency; + package = 3C78068B2B2D2D18007D58AE /* XCRemoteSwiftPackageReference "SwiftyJSON" */; + productName = SwiftyJSON; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 46056EAC1A19624E00C37628 /* Project object */; } diff --git a/Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/contents.xcworkspacedata index bd550bd..919434a 100644 --- a/Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..44e4bc8 --- /dev/null +++ b/Quiz Server/Quiz Server.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,23 @@ +{ + "pins" : [ + { + "identity" : "starscream", + "kind" : "remoteSourceControl", + "location" : "https://github.com/daltoniam/Starscream.git", + "state" : { + "revision" : "ac6c0fc9da221873e01bd1a0d4818498a71eef33", + "version" : "4.0.6" + } + }, + { + "identity" : "swiftyjson", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SwiftyJSON/SwiftyJSON.git", + "state" : { + "revision" : "b3dcd7dbd0d488e1a7077cb33b00f2083e382f07", + "version" : "5.0.1" + } + } + ], + "version" : 2 +} diff --git a/Quiz Server/Quiz Server/ControllerWindowController.swift b/Quiz Server/Quiz Server/ControllerWindowController.swift index 0f5a69b..14bc489 100644 --- a/Quiz Server/Quiz Server/ControllerWindowController.swift +++ b/Quiz Server/Quiz Server/ControllerWindowController.swift @@ -47,8 +47,6 @@ class ControllerWindowController: NSWindowController, NSWindowDelegate, NSTabVie @IBOutlet weak var buzzerButton14: NSButton! @IBOutlet weak var buzzerButton15: NSButton! - - @IBOutlet var textShowQuestionNumbers: NSButton! @IBOutlet weak var buzzcocksMode: NSButton! @IBOutlet weak var buzzerQueueMode: NSButton! @@ -93,10 +91,11 @@ class ControllerWindowController: NSWindowController, NSWindowDelegate, NSTabVie let quizView = SpriteKitViewController(nibName: "SpriteKitViewController", bundle: nil) var quizWindow: NSWindow? - var socket = WebSocket(url: URL(string: "ws://localhost:8091/")!) - - private func socketWriteIfConnected(_ s : String) { - if socket.isConnected { + var socket = WebSocket(request: URLRequest(url: URL(string: "ws://localhost:8091/")!)) + var socketIsConnected = false + + func socketWriteIfConnected(_ s : String) { + if socketIsConnected { socket.write(string: s) } } @@ -449,7 +448,7 @@ class ControllerWindowController: NSWindowController, NSWindowDelegate, NSTabVie @IBOutlet var textTeamGuesses: NSTextField! @IBOutlet var numbersTeamGuesses: NSTextField! - public func websocketDidReceiveMessage(socket: WebSocketClient, text: String) { + public func websocketDidReceiveMessage(text: String) { if(text.count >= 3) { switch(String(text.prefix(2))) { case "co": @@ -568,4 +567,41 @@ class ControllerWindowController: NSWindowController, NSWindowDelegate, NSTabVie @IBAction func disassociateTeamPress(_ sender: NSButtonCell) { socketWriteIfConnected("di\(sender.tag)") } + + func didReceive(event: Starscream.WebSocketEvent, client: Starscream.WebSocketClient) { + switch event { + case .connected(let headers): + socketIsConnected = true + print("websocket is connected: \(headers)") + case .disconnected(let reason, let code): + socketIsConnected = false + print("websocket is disconnected: \(reason) with code: \(code)") + case .text(let string): + websocketDidReceiveMessage(text: string) + case .binary(let data): + print("Received binary data: \(data.count)") + case .ping(_): + break + case .pong(_): + break + case .viabilityChanged(_): + break + case .reconnectSuggested(_): + break + case .cancelled: + socketIsConnected = false + case .error(let error): + socketIsConnected = false + if let e = error as? WSError { + print("websocket encountered an error: \(e.message)") + } else if let e = error { + print("websocket encountered an error: \(e.localizedDescription)") + } else { + print("websocket encountered an error") + } + case .peerClosed: + break + } + } + } diff --git a/Quiz Server/Quiz Server/LEDWebSocket.swift b/Quiz Server/Quiz Server/LEDWebSocket.swift index 48aca35..d45a225 100644 --- a/Quiz Server/Quiz Server/LEDWebSocket.swift +++ b/Quiz Server/Quiz Server/LEDWebSocket.swift @@ -12,9 +12,8 @@ import Starscream extension WebSocket { func sendIfConnected(_ s : String) { - if isConnected { - write(string: s) - } + let cwc = self.delegate as! ControllerWindowController + cwc.socketWriteIfConnected(s) } func ledsOff() { diff --git a/Quiz Server/SwiftyJSON/SwiftyJSON.swift b/Quiz Server/SwiftyJSON/SwiftyJSON.swift deleted file mode 100644 index 0681a5b..0000000 --- a/Quiz Server/SwiftyJSON/SwiftyJSON.swift +++ /dev/null @@ -1,1440 +0,0 @@ -// SwiftyJSON.swift -// -// Copyright (c) 2014 - 2016 Ruoyu Fu, Pinglin Tang -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -// MARK: - Error - -///Error domain -public let ErrorDomain: String = "SwiftyJSONErrorDomain" - -///Error code -public let ErrorUnsupportedType: Int = 999 -public let ErrorIndexOutOfBounds: Int = 900 -public let ErrorWrongType: Int = 901 -public let ErrorNotExist: Int = 500 -public let ErrorInvalidJSON: Int = 490 - -// MARK: - JSON Type - -/** - JSON's type definitions. - - See http://www.json.org - */ -public enum Type :Int{ - - case number - case string - case bool - case array - case dictionary - case null - case unknown -} - -// MARK: - JSON Base -public struct JSON { - - /** - Creates a JSON using the data. - - - parameter data: The NSData used to convert to json.Top level object in data is an NSArray or NSDictionary - - parameter opt: The JSON serialization reading options. `.AllowFragments` by default. - - parameter error: The NSErrorPointer used to return the error. `nil` by default. - - - returns: The created JSON - */ - public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer = nil) { - do { - let object: Any = try JSONSerialization.jsonObject(with: data, options: opt) - self.init(object) - } catch let aError as NSError { - if error != nil { - error?.pointee = aError - } - self.init(NSNull()) - } - } - - /** - Creates a JSON from JSON string - - parameter string: Normal json string like '{"a":"b"}' - - - returns: The created JSON - */ - public static func parse(_ string:String) -> JSON { - return string.data(using: String.Encoding.utf8) - .flatMap{ JSON(data: $0) } ?? JSON(NSNull()) - } - - /** - Creates a JSON using the object. - - - parameter object: The object must have the following properties: All objects are NSString/String, NSNumber/Int/Float/Double/Bool, NSArray/Array, NSDictionary/Dictionary, or NSNull; All dictionary keys are NSStrings/String; NSNumbers are not NaN or infinity. - - - returns: The created JSON - */ - public init(_ object: Any) { - self.object = object - } - - /** - Creates a JSON from a [JSON] - - - parameter jsonArray: A Swift array of JSON objects - - - returns: The created JSON - */ - public init(_ jsonArray:[JSON]) { - self.init(jsonArray.map { $0.object }) - } - - /** - Creates a JSON from a [String: JSON] - - - parameter jsonDictionary: A Swift dictionary of JSON objects - - - returns: The created JSON - */ - public init(_ jsonDictionary:[String: JSON]) { - var dictionary = [String: Any](minimumCapacity: jsonDictionary.count) - for (key, json) in jsonDictionary { - dictionary[key] = json.object - } - self.init(dictionary) - } - - /// Private object - fileprivate var rawArray: [Any] = [] - fileprivate var rawDictionary: [String : Any] = [:] - fileprivate var rawString: String = "" - fileprivate var rawNumber: NSNumber = 0 - fileprivate var rawNull: NSNull = NSNull() - fileprivate var rawBool: Bool = false - /// Private type - fileprivate var _type: Type = .null - /// prviate error - fileprivate var _error: NSError? = nil - - /// Object in JSON - public var object: Any { - get { - switch self.type { - case .array: - return self.rawArray - case .dictionary: - return self.rawDictionary - case .string: - return self.rawString - case .number: - return self.rawNumber - case .bool: - return self.rawBool - default: - return self.rawNull - } - } - set { - _error = nil - switch newValue { - case let number as NSNumber: - if number.isBool { - _type = .bool - self.rawBool = number.boolValue - } else { - _type = .number - self.rawNumber = number - } - case let string as String: - _type = .string - self.rawString = string - case _ as NSNull: - _type = .null - case _ as [JSON]: - _type = .array - case nil: - _type = .null - case let array as [Any]: - _type = .array - self.rawArray = array - case let dictionary as [String : Any]: - _type = .dictionary - self.rawDictionary = dictionary - default: - _type = .unknown - _error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"]) - } - } - } - - /// JSON type - public var type: Type { get { return _type } } - - /// Error in JSON - public var error: NSError? { get { return self._error } } - - /// The static null JSON - @available(*, unavailable, renamed:"null") - public static var nullJSON: JSON { get { return null } } - public static var null: JSON { get { return JSON(NSNull()) } } -} - -public enum JSONIndex:Comparable -{ - case array(Int) - case dictionary(DictionaryIndex) - case null - - static public func ==(lhs: JSONIndex, rhs: JSONIndex) -> Bool - { - switch (lhs, rhs) - { - case (.array(let left), .array(let right)): - return left == right - case (.dictionary(let left), .dictionary(let right)): - return left == right - case (.null, .null): return true - default: - return false - } - } - - static public func <(lhs: JSONIndex, rhs: JSONIndex) -> Bool - { - switch (lhs, rhs) - { - case (.array(let left), .array(let right)): - return left < right - case (.dictionary(let left), .dictionary(let right)): - return left < right - default: - return false - } - } - -} - -public enum JSONRawIndex: Comparable -{ - case array(Int) - case dictionary(DictionaryIndex) - case null - - static public func ==(lhs: JSONRawIndex, rhs: JSONRawIndex) -> Bool - { - switch (lhs, rhs) - { - case (.array(let left), .array(let right)): - return left == right - case (.dictionary(let left), .dictionary(let right)): - return left == right - case (.null, .null): return true - default: - return false - } - } - - static public func <(lhs: JSONRawIndex, rhs: JSONRawIndex) -> Bool - { - switch (lhs, rhs) - { - case (.array(let left), .array(let right)): - return left < right - case (.dictionary(let left), .dictionary(let right)): - return left < right - default: - return false - } - } - - -} - -extension JSON: Collection -{ - - public typealias Index = JSONRawIndex - - public var startIndex: Index - { - switch type - { - case .array: - return .array(rawArray.startIndex) - case .dictionary: - return .dictionary(rawDictionary.startIndex) - default: - return .null - } - } - - public var endIndex: Index - { - switch type - { - case .array: - return .array(rawArray.endIndex) - case .dictionary: - return .dictionary(rawDictionary.endIndex) - default: - return .null - } - } - - public func index(after i: Index) -> Index - { - switch i - { - case .array(let idx): - return .array(rawArray.index(after: idx)) - case .dictionary(let idx): - return .dictionary(rawDictionary.index(after: idx)) - default: - return .null - } - - } - - public subscript (position: Index) -> (String, JSON) - { - switch position - { - case .array(let idx): - return (String(idx), JSON(self.rawArray[idx])) - case .dictionary(let idx): - let (key, value) = self.rawDictionary[idx] - return (key, JSON(value)) - default: - return ("", JSON.null) - } - } - - -} - -// MARK: - Subscript - -/** - * To mark both String and Int can be used in subscript. - */ -public enum JSONKey -{ - case index(Int) - case key(String) -} - -public protocol JSONSubscriptType { - var jsonKey:JSONKey { get } -} - -extension Int: JSONSubscriptType { - public var jsonKey:JSONKey { - return JSONKey.index(self) - } -} - -extension String: JSONSubscriptType { - public var jsonKey:JSONKey { - return JSONKey.key(self) - } -} - -extension JSON { - - /// If `type` is `.Array`, return json whose object is `array[index]`, otherwise return null json with error. - fileprivate subscript(index index: Int) -> JSON { - get { - if self.type != .array { - var r = JSON.null - r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] failure, It is not an array"]) - return r - } else if index >= 0 && index < self.rawArray.count { - return JSON(self.rawArray[index]) - } else { - var r = JSON.null - r._error = NSError(domain: ErrorDomain, code:ErrorIndexOutOfBounds , userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] is out of bounds"]) - return r - } - } - set { - if self.type == .array { - if self.rawArray.count > index && newValue.error == nil { - self.rawArray[index] = newValue.object - } - } - } - } - - /// If `type` is `.Dictionary`, return json whose object is `dictionary[key]` , otherwise return null json with error. - fileprivate subscript(key key: String) -> JSON { - get { - var r = JSON.null - if self.type == .dictionary { - if let o = self.rawDictionary[key] { - r = JSON(o) - } else { - r._error = NSError(domain: ErrorDomain, code: ErrorNotExist, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] does not exist"]) - } - } else { - r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] failure, It is not an dictionary"]) - } - return r - } - set { - if self.type == .dictionary && newValue.error == nil { - self.rawDictionary[key] = newValue.object - } - } - } - - /// If `sub` is `Int`, return `subscript(index:)`; If `sub` is `String`, return `subscript(key:)`. - fileprivate subscript(sub sub: JSONSubscriptType) -> JSON { - get { - switch sub.jsonKey { - case .index(let index): return self[index: index] - case .key(let key): return self[key: key] - } - } - set { - switch sub.jsonKey { - case .index(let index): self[index: index] = newValue - case .key(let key): self[key: key] = newValue - } - } - } - - /** - Find a json in the complex data structures by using array of Int and/or String as path. - - - parameter path: The target json's path. Example: - - let json = JSON[data] - let path = [9,"list","person","name"] - let name = json[path] - - The same as: let name = json[9]["list"]["person"]["name"] - - - returns: Return a json found by the path or a null json with error - */ - public subscript(path: [JSONSubscriptType]) -> JSON { - get { - return path.reduce(self) { $0[sub: $1] } - } - set { - switch path.count { - case 0: - return - case 1: - self[sub:path[0]].object = newValue.object - default: - var aPath = path; aPath.remove(at: 0) - var nextJSON = self[sub: path[0]] - nextJSON[aPath] = newValue - self[sub: path[0]] = nextJSON - } - } - } - - /** - Find a json in the complex data structures by using array of Int and/or String as path. - - - parameter path: The target json's path. Example: - - let name = json[9,"list","person","name"] - - The same as: let name = json[9]["list"]["person"]["name"] - - - returns: Return a json found by the path or a null json with error - */ - public subscript(path: JSONSubscriptType...) -> JSON { - get { - return self[path] - } - set { - self[path] = newValue - } - } -} - -// MARK: - LiteralConvertible - -extension JSON: Swift.ExpressibleByStringLiteral { - - public init(stringLiteral value: StringLiteralType) { - self.init(value as Any) - } - - public init(extendedGraphemeClusterLiteral value: StringLiteralType) { - self.init(value as Any) - } - - public init(unicodeScalarLiteral value: StringLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByIntegerLiteral { - - public init(integerLiteral value: IntegerLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByBooleanLiteral { - - public init(booleanLiteral value: BooleanLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByFloatLiteral { - - public init(floatLiteral value: FloatLiteralType) { - self.init(value as Any) - } -} - -extension JSON: Swift.ExpressibleByDictionaryLiteral { - public init(dictionaryLiteral elements: (String, Any)...) { - let array = elements - self.init(dictionaryLiteral: array) - } - - public init(dictionaryLiteral elements: [(String, Any)]) { - let jsonFromDictionaryLiteral: ([String : Any]) -> JSON = { dictionary in - let initializeElement = Array(dictionary.keys).compactMap { key -> (String, Any)? in - if let value = dictionary[key] { - return (key, value) - } - return nil - } - return JSON(dictionaryLiteral: initializeElement) - } - - var dict = [String : Any](minimumCapacity: elements.count) - - for element in elements { - let elementToSet: Any - if let json = element.1 as? JSON { - elementToSet = json.object - } else if let jsonArray = element.1 as? [JSON] { - elementToSet = JSON(jsonArray).object - } else if let dictionary = element.1 as? [String : Any] { - elementToSet = jsonFromDictionaryLiteral(dictionary).object - } else if let dictArray = element.1 as? [[String : Any]] { - let jsonArray = dictArray.map { jsonFromDictionaryLiteral($0) } - elementToSet = JSON(jsonArray).object - } else { - elementToSet = element.1 - } - dict[element.0] = elementToSet - } - - self.init(dict) - } -} - -extension JSON: Swift.ExpressibleByArrayLiteral { - - public init(arrayLiteral elements: Any...) { - self.init(elements as Any) - } -} - -extension JSON: Swift.ExpressibleByNilLiteral { - - @available(*, deprecated, message: "use JSON.null instead. Will be removed in future versions") - public init(nilLiteral: ()) { - self.init(NSNull() as Any) - } -} - -// MARK: - Raw - -extension JSON: Swift.RawRepresentable { - - public init?(rawValue: Any) { - if JSON(rawValue).type == .unknown { - return nil - } else { - self.init(rawValue) - } - } - - public var rawValue: Any { - return self.object - } - - public func rawData(options opt: JSONSerialization.WritingOptions = JSONSerialization.WritingOptions(rawValue: 0)) throws -> Data { - guard JSONSerialization.isValidJSONObject(self.object) else { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "JSON is invalid"]) - } - - return try JSONSerialization.data(withJSONObject: self.object, options: opt) - } - - public func rawString(_ encoding: String.Encoding = .utf8, options opt: JSONSerialization.WritingOptions = .prettyPrinted) -> String? { - do { - return try _rawString(encoding, options: [.jsonSerialization: opt]) - } catch { - print("Could not serialize object to JSON because:", error.localizedDescription) - return nil - } - } - - public func rawString(options: [writtingOptionsKeys: Any]) -> String? { - let encoding = options[.encoding] as? String.Encoding ?? String.Encoding.utf8 - let maxObjectDepth = options[.maxObjextDepth] as? Int ?? 10 - do { - return try _rawString(encoding, options: options, maxObjectDepth: maxObjectDepth) - } catch { - print("Could not serialize object to JSON because:", error.localizedDescription) - return nil - } - } - - private func _rawString( - _ encoding: String.Encoding = .utf8, - options: [writtingOptionsKeys: Any], - maxObjectDepth: Int = 10 - ) throws -> String? { - if (maxObjectDepth < 0) { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "Element too deep. Increase maxObjectDepth and make sure there is no reference loop"]) - } - switch self.type { - case .dictionary: - do { - if !(options[.castNilToNSNull] as? Bool ?? false) { - let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted - let data = try self.rawData(options: jsonOption) - return String(data: data, encoding: encoding) - } - - guard let dict = self.object as? [String: Any?] else { - return nil - } - let body = try dict.keys.map { key throws -> String in - guard let value = dict[key] else { - return "\"\(key)\": null" - } - guard let unwrappedValue = value else { - return "\"\(key)\": null" - } - - let nestedValue = JSON(unwrappedValue) - guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "Could not serialize nested JSON"]) - } - if nestedValue.type == .string { - return "\"\(key)\": \"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\"" - } else { - return "\"\(key)\": \(nestedString)" - } - } - - return "{\(body.joined(separator: ","))}" - } catch _ { - return nil - } - case .array: - do { - if !(options[.castNilToNSNull] as? Bool ?? false) { - let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted - let data = try self.rawData(options: jsonOption) - return String(data: data, encoding: encoding) - } - - guard let array = self.object as? [Any?] else { - return nil - } - let body = try array.map { value throws -> String in - guard let unwrappedValue = value else { - return "null" - } - - let nestedValue = JSON(unwrappedValue) - guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else { - throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "Could not serialize nested JSON"]) - } - if nestedValue.type == .string { - return "\"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\"" - } else { - return nestedString - } - } - - return "[\(body.joined(separator: ","))]" - } catch _ { - return nil - } - case .string: - return self.rawString - case .number: - return self.rawNumber.stringValue - case .bool: - return self.rawBool.description - case .null: - return "null" - default: - return nil - } - } -} - -// MARK: - Printable, DebugPrintable - -extension JSON: Swift.CustomStringConvertible, Swift.CustomDebugStringConvertible { - - public var description: String { - if let string = self.rawString(options:.prettyPrinted) { - return string - } else { - return "unknown" - } - } - - public var debugDescription: String { - return description - } -} - -// MARK: - Array - -extension JSON { - - //Optional [JSON] - public var array: [JSON]? { - get { - if self.type == .array { - return self.rawArray.map{ JSON($0) } - } else { - return nil - } - } - } - - //Non-optional [JSON] - public var arrayValue: [JSON] { - get { - return self.array ?? [] - } - } - - //Optional [Any] - public var arrayObject: [Any]? { - get { - switch self.type { - case .array: - return self.rawArray - default: - return nil - } - } - set { - if let array = newValue { - self.object = array as Any - } else { - self.object = NSNull() - } - } - } -} - -// MARK: - Dictionary - -extension JSON { - - //Optional [String : JSON] - public var dictionary: [String : JSON]? { - if self.type == .dictionary { - var d = [String : JSON](minimumCapacity: rawDictionary.count) - for (key, value) in rawDictionary { - d[key] = JSON(value) - } - return d - } else { - return nil - } - } - - //Non-optional [String : JSON] - public var dictionaryValue: [String : JSON] { - return self.dictionary ?? [:] - } - - //Optional [String : Any] - - public var dictionaryObject: [String : Any]? { - get { - switch self.type { - case .dictionary: - return self.rawDictionary - default: - return nil - } - } - set { - if let v = newValue { - self.object = v as Any - } else { - self.object = NSNull() - } - } - } -} - -// MARK: - Bool - -extension JSON { // : Swift.Bool - - //Optional bool - public var bool: Bool? { - get { - switch self.type { - case .bool: - return self.rawBool - default: - return nil - } - } - set { - if let newValue = newValue { - self.object = newValue as Bool - } else { - self.object = NSNull() - } - } - } - - //Non-optional bool - public var boolValue: Bool { - get { - switch self.type { - case .bool: - return self.rawBool - case .number: - return self.rawNumber.boolValue - case .string: - return ["true", "y", "t"].contains() { (truthyString) in - return self.rawString.caseInsensitiveCompare(truthyString) == .orderedSame - } - default: - return false - } - } - set { - self.object = newValue - } - } -} - -// MARK: - String - -extension JSON { - - //Optional string - public var string: String? { - get { - switch self.type { - case .string: - return self.object as? String - default: - return nil - } - } - set { - if let newValue = newValue { - self.object = NSString(string:newValue) - } else { - self.object = NSNull() - } - } - } - - //Non-optional string - public var stringValue: String { - get { - switch self.type { - case .string: - return self.object as? String ?? "" - case .number: - return self.rawNumber.stringValue - case .bool: - return (self.object as? Bool).map { String($0) } ?? "" - default: - return "" - } - } - set { - self.object = NSString(string:newValue) - } - } -} - -// MARK: - Number -extension JSON { - - //Optional number - public var number: NSNumber? { - get { - switch self.type { - case .number: - return self.rawNumber - case .bool: - return NSNumber(value: self.rawBool ? 1 : 0) - default: - return nil - } - } - set { - self.object = newValue ?? NSNull() - } - } - - //Non-optional number - public var numberValue: NSNumber { - get { - switch self.type { - case .string: - let decimal = NSDecimalNumber(string: self.object as? String) - if decimal == NSDecimalNumber.notANumber { // indicates parse error - return NSDecimalNumber.zero - } - return decimal - case .number: - return self.object as? NSNumber ?? NSNumber(value: 0) - case .bool: - return NSNumber(value: self.rawBool ? 1 : 0) - default: - return NSNumber(value: 0.0) - } - } - set { - self.object = newValue - } - } -} - -//MARK: - Null -extension JSON { - - public var null: NSNull? { - get { - switch self.type { - case .null: - return self.rawNull - default: - return nil - } - } - set { - self.object = NSNull() - } - } - public func exists() -> Bool{ - if let errorValue = error, errorValue.code == ErrorNotExist || - errorValue.code == ErrorIndexOutOfBounds || - errorValue.code == ErrorWrongType { - return false - } - return true - } -} - -//MARK: - URL -extension JSON { - - //Optional URL - public var URL: URL? { - get { - switch self.type { - case .string: - // Check for existing percent escapes first to prevent double-escaping of % character - if let _ = self.rawString.range(of: "%[0-9A-Fa-f]{2}", options: .regularExpression, range: nil, locale: nil) { - return Foundation.URL(string: self.rawString) - } else if let encodedString_ = self.rawString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) { - // We have to use `Foundation.URL` otherwise it conflicts with the variable name. - return Foundation.URL(string: encodedString_) - } else { - return nil - } - default: - return nil - } - } - set { - self.object = newValue?.absoluteString ?? NSNull() - } - } -} - -// MARK: - Int, Double, Float, Int8, Int16, Int32, Int64 - -extension JSON { - - public var double: Double? { - get { - return self.number?.doubleValue - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var doubleValue: Double { - get { - return self.numberValue.doubleValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var float: Float? { - get { - return self.number?.floatValue - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var floatValue: Float { - get { - return self.numberValue.floatValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int: Int? - { - get - { - return self.number?.intValue - } - set - { - if let newValue = newValue - { - self.object = NSNumber(value: newValue) - } else - { - self.object = NSNull() - } - } - } - - public var intValue: Int { - get { - return self.numberValue.intValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt: UInt? { - get { - return self.number?.uintValue - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uIntValue: UInt { - get { - return self.numberValue.uintValue - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int8: Int8? { - get { - return self.number?.int8Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: Int(newValue)) - } else { - self.object = NSNull() - } - } - } - - public var int8Value: Int8 { - get { - return self.numberValue.int8Value - } - set { - self.object = NSNumber(value: Int(newValue)) - } - } - - public var uInt8: UInt8? { - get { - return self.number?.uint8Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt8Value: UInt8 { - get { - return self.numberValue.uint8Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int16: Int16? { - get { - return self.number?.int16Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var int16Value: Int16 { - get { - return self.numberValue.int16Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt16: UInt16? { - get { - return self.number?.uint16Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt16Value: UInt16 { - get { - return self.numberValue.uint16Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int32: Int32? { - get { - return self.number?.int32Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var int32Value: Int32 { - get { - return self.numberValue.int32Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt32: UInt32? { - get { - return self.number?.uint32Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt32Value: UInt32 { - get { - return self.numberValue.uint32Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var int64: Int64? { - get { - return self.number?.int64Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var int64Value: Int64 { - get { - return self.numberValue.int64Value - } - set { - self.object = NSNumber(value: newValue) - } - } - - public var uInt64: UInt64? { - get { - return self.number?.uint64Value - } - set { - if let newValue = newValue { - self.object = NSNumber(value: newValue) - } else { - self.object = NSNull() - } - } - } - - public var uInt64Value: UInt64 { - get { - return self.numberValue.uint64Value - } - set { - self.object = NSNumber(value: newValue) - } - } -} - -//MARK: - Comparable -extension JSON : Swift.Comparable {} - -public func ==(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber == rhs.rawNumber - case (.string, .string): - return lhs.rawString == rhs.rawString - case (.bool, .bool): - return lhs.rawBool == rhs.rawBool - case (.array, .array): - return lhs.rawArray as NSArray == rhs.rawArray as NSArray - case (.dictionary, .dictionary): - return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary - case (.null, .null): - return true - default: - return false - } -} - -public func <=(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber <= rhs.rawNumber - case (.string, .string): - return lhs.rawString <= rhs.rawString - case (.bool, .bool): - return lhs.rawBool == rhs.rawBool - case (.array, .array): - return lhs.rawArray as NSArray == rhs.rawArray as NSArray - case (.dictionary, .dictionary): - return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary - case (.null, .null): - return true - default: - return false - } -} - -public func >=(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber >= rhs.rawNumber - case (.string, .string): - return lhs.rawString >= rhs.rawString - case (.bool, .bool): - return lhs.rawBool == rhs.rawBool - case (.array, .array): - return lhs.rawArray as NSArray == rhs.rawArray as NSArray - case (.dictionary, .dictionary): - return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary - case (.null, .null): - return true - default: - return false - } -} - -public func >(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber > rhs.rawNumber - case (.string, .string): - return lhs.rawString > rhs.rawString - default: - return false - } -} - -public func <(lhs: JSON, rhs: JSON) -> Bool { - - switch (lhs.type, rhs.type) { - case (.number, .number): - return lhs.rawNumber < rhs.rawNumber - case (.string, .string): - return lhs.rawString < rhs.rawString - default: - return false - } -} - -private let trueNumber = NSNumber(value: true) -private let falseNumber = NSNumber(value: false) -private let trueObjCType = String(cString: trueNumber.objCType) -private let falseObjCType = String(cString: falseNumber.objCType) - -// MARK: - NSNumber: Comparable - -extension NSNumber { - var isBool:Bool { - get { - let objCType = String(cString: self.objCType) - if (self.compare(trueNumber) == .orderedSame && objCType == trueObjCType) || (self.compare(falseNumber) == .orderedSame && objCType == falseObjCType){ - return true - } else { - return false - } - } - } -} - -func ==(lhs: NSNumber, rhs: NSNumber) -> Bool { - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) == .orderedSame - } -} - -func !=(lhs: NSNumber, rhs: NSNumber) -> Bool { - return !(lhs == rhs) -} - -func <(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) == .orderedAscending - } -} - -func >(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) == ComparisonResult.orderedDescending - } -} - -func <=(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) != .orderedDescending - } -} - -func >=(lhs: NSNumber, rhs: NSNumber) -> Bool { - - switch (lhs.isBool, rhs.isBool) { - case (false, true): - return false - case (true, false): - return false - default: - return lhs.compare(rhs) != .orderedAscending - } -} - -public enum writtingOptionsKeys { - case jsonSerialization - case castNilToNSNull - case maxObjextDepth - case encoding -} diff --git a/Starscream b/Starscream deleted file mode 160000 index e6b65c6..0000000 --- a/Starscream +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e6b65c6d9077ea48b4a7bdda8994a1d3c6969c8d