diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index 24ee8c234..36f9526d7 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -25,6 +25,9 @@ 6401A5162A582141009BA686 /* SystemPropertyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8088D77829C498FA00F240CB /* SystemPropertyTest.swift */; }; 6406F2572AD9820700B58C42 /* NativePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6406F2562AD9820700B58C42 /* NativePublisher.swift */; }; 6406F25B2AD987EB00B58C42 /* PublisherTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6406F25A2AD987EB00B58C42 /* PublisherTest.swift */; }; + 640885C82B1F7C3200E6CF88 /* QdsTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640885C72B1F7C3200E6CF88 /* QdsTool.swift */; }; + 640885CA2B1F7EE700E6CF88 /* QdsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640885C92B1F7EE700E6CF88 /* QdsUtils.swift */; }; + 640885CC2B1F7F0100E6CF88 /* NativeQdsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640885CB2B1F7F0100E6CF88 /* NativeQdsUtils.swift */; }; 64098F4B2ACD6B2E0020D741 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64098F492ACD6AF20020D741 /* SceneDelegate.swift */; }; 64098F4E2ACD73920020D741 /* PerfTestEventListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64098F4C2ACD73820020D741 /* PerfTestEventListener.swift */; }; 64098F4F2ACD73930020D741 /* PerfTestEventListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64098F4C2ACD73820020D741 /* PerfTestEventListener.swift */; }; @@ -542,6 +545,9 @@ 640885C42B1F477A00E6CF88 /* DxFeedIpfConnect.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DxFeedIpfConnect.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 640885C52B1F553C00E6CF88 /* DXFeedLiveIpfSample.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DXFeedLiveIpfSample.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 640885C62B1F657300E6CF88 /* ScheduleSample.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = ScheduleSample.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 640885C72B1F7C3200E6CF88 /* QdsTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QdsTool.swift; sourceTree = ""; }; + 640885C92B1F7EE700E6CF88 /* QdsUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QdsUtils.swift; sourceTree = ""; }; + 640885CB2B1F7F0100E6CF88 /* NativeQdsUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeQdsUtils.swift; sourceTree = ""; }; 6408BB712B1F2D14005D7797 /* WriteTapeFile.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = WriteTapeFile.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 64098F492ACD6AF20020D741 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 64098F4C2ACD73820020D741 /* PerfTestEventListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerfTestEventListener.swift; sourceTree = ""; }; @@ -968,6 +974,7 @@ 648BD56A2AC4576F004A3A95 /* HelpTool.swift */, 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */, 641E45F82B1DE51700649363 /* EventsListener.swift */, + 640885C72B1F7C3200E6CF88 /* QdsTool.swift */, ); path = Tools; sourceTree = ""; @@ -1176,6 +1183,7 @@ 64C772002A975102009868C2 /* Reference+Util.swift */, 6464074E2A9F62D4006FF769 /* Date+Ext.swift */, 64A42F3A2B07A7A3001C3ACC /* SymbolParser.swift */, + 640885C92B1F7EE700E6CF88 /* QdsUtils.swift */, ); path = Utils; sourceTree = ""; @@ -1299,6 +1307,7 @@ 64A42F462B0B9367001C3ACC /* NativeTimeZone.swift */, 64A42F482B0B9683001C3ACC /* NativeTimeFormat.swift */, 64A42F4A2B0B96EF001C3ACC /* NativeTimePeriod.swift */, + 640885CB2B1F7F0100E6CF88 /* NativeQdsUtils.swift */, ); path = Utils; sourceTree = ""; @@ -2115,6 +2124,7 @@ files = ( 648BD56D2AC56A04004A3A95 /* SubscriptionUtils.swift in Sources */, 648BD56B2AC4576F004A3A95 /* HelpTool.swift in Sources */, + 640885C82B1F7C3200E6CF88 /* QdsTool.swift in Sources */, 649282E82AD54919008F0F04 /* ScheduleUtils.swift in Sources */, 647426AF2ABC93900012F793 /* EventCode+String.swift in Sources */, 645BE8542AC3229D0028243D /* ToolsCommand.swift in Sources */, @@ -2309,6 +2319,7 @@ 64278C702A602FA00074B5AA /* Candle+Ext.swift in Sources */, 64B4363C2AB86F3C0003919E /* DayFilter+Ext.swift in Sources */, 6464075B2AA0CEF2006FF769 /* NativeExecutor.swift in Sources */, + 640885CC2B1F7F0100E6CF88 /* NativeQdsUtils.swift in Sources */, 6486B97B2AD0517A00D8D5FA /* OrderAction.swift in Sources */, 64DA26B82AA20095005B1757 /* NativeInstrumentProfileConnection.swift in Sources */, 64104FC32A210F2400D1FC41 /* EventCode+Native.swift in Sources */, @@ -2403,6 +2414,7 @@ 6447A5DF2A8E56FC00739CCF /* IIndexedEvent.swift in Sources */, 64104FC52A26059B00D1FC41 /* ConcurrentSet.swift in Sources */, 64BA925F2A306B9600BE26A0 /* Profile.swift in Sources */, + 640885CA2B1F7EE700E6CF88 /* QdsUtils.swift in Sources */, 64BA92672A306E3100BE26A0 /* Trade+Ext.swift in Sources */, 640C3FD62A6179E300555161 /* CandleAlignment.swift in Sources */, 640C3FCC2A616B6200555161 /* ArgumentException.swift in Sources */, diff --git a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme index b3e0da452..36346ad18 100644 --- a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme +++ b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme @@ -61,6 +61,14 @@ + + + + + } + let classes = UnsafeMutablePointer?> + .allocate(capacity: parameters.count) + var iterator = classes + for code in parameters { + iterator.initialize(to: code.toCStringRef()) + iterator = iterator.successor() + } + + let list = UnsafeMutablePointer.allocate(capacity: 1) + list.pointee.size = Int32(parameters.count) + list.pointee.elements = classes + _ = try ErrorCheck.nativeCall(thread, dxfg_Tools_main(thread, list)) + + classes.deinitialize(count: parameters.count) + classes.deallocate() + list.deinitialize(count: 1) + list.deallocate() + } +} diff --git a/DXFeedFramework/Utils/QdsUtils.swift b/DXFeedFramework/Utils/QdsUtils.swift new file mode 100644 index 000000000..069ec928b --- /dev/null +++ b/DXFeedFramework/Utils/QdsUtils.swift @@ -0,0 +1,14 @@ +// +// QdsUtils.swift +// DXFeedFramework +// +// Created by Aleksey Kosylo on 05.12.23. +// + +import Foundation + +public class QdsUtils { + public static func execute(_ parameters: [String]) throws { + try NativeQdsUtils.execute(parameters) + } +} diff --git a/DXFeedFrameworkTests/DXConnectionTest.swift b/DXFeedFrameworkTests/DXConnectionTest.swift index 4a7b4eac7..05018b155 100644 --- a/DXFeedFrameworkTests/DXConnectionTest.swift +++ b/DXFeedFrameworkTests/DXConnectionTest.swift @@ -47,13 +47,15 @@ final class DXConnectionTest: XCTestCase { // For token-based authorization, use the following address format: // "dxlink:wss://demo.dxfeed.com/dxlink-ws[login=dxlink:token]" let endpoint = try DXEndpoint.builder() - .withProperty("dxfeed.address", "dxlink:wss://demo.dxfeed.com/dxlink-ws") .build() + let subscription = try endpoint.getFeed()?.createSubscription(EventCode.quote) let receivedEventsExpectation = expectation(description: "Received events") let eventListener = DXConnectionListener(expectation: receivedEventsExpectation) try subscription?.add(listener: eventListener) try subscription?.addSymbols("AAPL") + try endpoint.connect("dxlink:wss://demo.dxfeed.com/dxlink-ws") + wait(for: [receivedEventsExpectation], timeout: 2) } @@ -61,13 +63,14 @@ final class DXConnectionTest: XCTestCase { // For token-based authorization, use the following address format: // "demo.dxfeed.com:7300[login=entitle:token]" let endpoint = try DXEndpoint.builder() - .withProperty("dxfeed.address", "demo.dxfeed.com:7300") .build() let subscription = try endpoint.getFeed()?.createSubscription(EventCode.quote) let receivedEventsExpectation = expectation(description: "Received events") let eventListener = DXConnectionListener(expectation: receivedEventsExpectation) try subscription?.add(listener: eventListener) try subscription?.addSymbols("AAPL") + try endpoint.connect("demo.dxfeed.com:7300") + wait(for: [receivedEventsExpectation], timeout: 2) } diff --git a/README.md b/README.md index 88e952c28..f19dd352c 100644 --- a/README.md +++ b/README.md @@ -140,13 +140,12 @@ class Listener: DXEventListener { // For token-based authorization, use the following address format: // "demo.dxfeed.com:7300[login=entitle:token]" -let endpoint = try DXEndpoint.builder() - .withProperty("dxfeed.address", "demo.dxfeed.com:7300") - .build() +let endpoint = try DXEndpoint.builder().build() let subscription = try endpoint.getFeed()?.createSubscription(EventCode.quote) let eventListener = Listener() try subscription?.add(listener: eventListener) try subscription?.addSymbols("AAPL") +try endpoint.connect("demo.dxfeed.com:7300") ```
@@ -186,13 +185,12 @@ try SystemProperty.setProperty("dxfeed.experimental.dxlink.enable", "true") try SystemProperty.setProperty("scheme", "ext:resource:dxlink.xml") // For token-based authorization, use the following address format: // "dxlink:wss://demo.dxfeed.com/dxlink-ws[login=dxlink:token]" -let endpoint = try DXEndpoint.builder() - .withProperty("dxfeed.address", "dxlink:wss://demo.dxfeed.com/dxlink-ws") - .build() +let endpoint = try DXEndpoint.builder().build() let subscription = try endpoint.getFeed()?.createSubscription(EventCode.quote) let eventListener = Listener() try subscription?.add(listener: eventListener) try subscription?.addSymbols("AAPL") +try endpoint.connect("dxlink:wss://demo.dxfeed.com/dxlink-ws") ```
Output diff --git a/Samples/Tools/Arguments.swift b/Samples/Tools/Arguments.swift index 277441b8f..103445704 100644 --- a/Samples/Tools/Arguments.swift +++ b/Samples/Tools/Arguments.swift @@ -69,6 +69,21 @@ class Arguments { return nil }() + public lazy var qdsCommandLine: [String]? = { + var result = [String]() + for str in namelessParameters[1.. [] + +Where: + + value pos. 0 Required. + -p, --properties Comma-separated list of properties (key-value pair separated by an equals sign). +""" + + private lazy var arguments: Arguments = { + do { + let arguments = try Arguments(ProcessInfo.processInfo.arguments, requiredNumberOfArguments: 1) + return arguments + } catch { + print(fullDescription) + exit(0) + } + }() + + func execute() { + do { + try arguments.properties.forEach { key, value in + try SystemProperty.setProperty(key, value) + } + try QdsUtils.execute(arguments.qdsCommandLine ?? [String]()) + } catch { + print("Qds tool error: \(error)") + } + + } +} diff --git a/Samples/Tools/main.swift b/Samples/Tools/main.swift index c93b2a417..12e368c85 100644 --- a/Samples/Tools/main.swift +++ b/Samples/Tools/main.swift @@ -11,10 +11,11 @@ let commands: [ToolsCommand] = [PerfTestTool(), ConnectTool(), LatencyTestTool(), DumpTool(), + QdsTool(), HelpTool()] func getCommand(_ cmd: String) -> ToolsCommand? { - var cmd = cmd.lowercased() + let cmd = cmd.lowercased() return commands.first { command in command.cmd.lowercased() == cmd }