Skip to content

Commit

Permalink
add qds tools
Browse files Browse the repository at this point in the history
update readme.md
  • Loading branch information
kosyloa committed Dec 6, 2023
1 parent 076b5d7 commit 0c50a94
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 10 deletions.
12 changes: 12 additions & 0 deletions DXFeedFramework.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -542,6 +545,9 @@
640885C42B1F477A00E6CF88 /* DxFeedIpfConnect.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DxFeedIpfConnect.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
640885C52B1F553C00E6CF88 /* DXFeedLiveIpfSample.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DXFeedLiveIpfSample.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
640885C62B1F657300E6CF88 /* ScheduleSample.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = ScheduleSample.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
640885C72B1F7C3200E6CF88 /* QdsTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QdsTool.swift; sourceTree = "<group>"; };
640885C92B1F7EE700E6CF88 /* QdsUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QdsUtils.swift; sourceTree = "<group>"; };
640885CB2B1F7F0100E6CF88 /* NativeQdsUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeQdsUtils.swift; sourceTree = "<group>"; };
6408BB712B1F2D14005D7797 /* WriteTapeFile.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = WriteTapeFile.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
64098F492ACD6AF20020D741 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
64098F4C2ACD73820020D741 /* PerfTestEventListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerfTestEventListener.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -968,6 +974,7 @@
648BD56A2AC4576F004A3A95 /* HelpTool.swift */,
648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */,
641E45F82B1DE51700649363 /* EventsListener.swift */,
640885C72B1F7C3200E6CF88 /* QdsTool.swift */,
);
path = Tools;
sourceTree = "<group>";
Expand Down Expand Up @@ -1176,6 +1183,7 @@
64C772002A975102009868C2 /* Reference+Util.swift */,
6464074E2A9F62D4006FF769 /* Date+Ext.swift */,
64A42F3A2B07A7A3001C3ACC /* SymbolParser.swift */,
640885C92B1F7EE700E6CF88 /* QdsUtils.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -1299,6 +1307,7 @@
64A42F462B0B9367001C3ACC /* NativeTimeZone.swift */,
64A42F482B0B9683001C3ACC /* NativeTimeFormat.swift */,
64A42F4A2B0B96EF001C3ACC /* NativeTimePeriod.swift */,
640885CB2B1F7F0100E6CF88 /* NativeQdsUtils.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@
</CommandLineArgument>
<CommandLineArgument
argument = "Connect demo.dxfeed.com:7300 TimeAndSale &quot;ipf[https://demo:[email protected]/ipf?TYPE=STOCK&amp;compression=zip],APPL&quot; -p monitoring.stat=1s"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "qds connect demo.dxfeed.com:7300 Quote AAPL,IBM"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "qds &quot;connect &quot;dxlink:wss://demo.dxfeed.com/dxlink-ws&quot; Quote AAPL&quot; -p dxfeed.experimental.dxlink.enable=true,scheme=ext:resource:dxlink.xml "
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
Expand Down
35 changes: 35 additions & 0 deletions DXFeedFramework/Native/Utils/NativeQdsUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// NativeQdsUtils.swift
// DXFeedFramework
//
// Created by Aleksey Kosylo on 05.12.23.
//

import Foundation
@_implementationOnly import graal_api

class NativeQdsUtils {
static func execute(_ parameters: [String]) throws {
let thread = currentThread()
let cStrings = parameters.map { str in
str.toCStringRef() as UnsafePointer<CChar>
}
let classes = UnsafeMutablePointer<UnsafePointer<CChar>?>
.allocate(capacity: parameters.count)
var iterator = classes
for code in parameters {
iterator.initialize(to: code.toCStringRef())
iterator = iterator.successor()
}

let list = UnsafeMutablePointer<dxfg_string_list>.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()
}
}
14 changes: 14 additions & 0 deletions DXFeedFramework/Utils/QdsUtils.swift
Original file line number Diff line number Diff line change
@@ -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)
}
}
7 changes: 5 additions & 2 deletions DXFeedFrameworkTests/DXConnectionTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,30 @@ 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)
}

func testConnection() throws {
// 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)
}

Expand Down
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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")
```

<details>
Expand Down Expand Up @@ -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")
```
<details>
<summary>Output</summary>
Expand Down
15 changes: 15 additions & 0 deletions Samples/Tools/Arguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@ class Arguments {
return nil
}()

public lazy var qdsCommandLine: [String]? = {
var result = [String]()
for str in namelessParameters[1..<namelessParameters.count] {
let splited = str.split(separator: " ")
if splited.count == 1 {
result.append(str)
} else {
splited.forEach { substring in
result.append(String(substring))
}
}
}
return result
}()

init(_ cmd: [String], requiredNumberOfArguments: Int) throws {
print("Parse \(cmd) to \(requiredNumberOfArguments) arguments")

Expand Down
3 changes: 2 additions & 1 deletion Samples/Tools/ConnectTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ Where:
123456789 - value-in-milliseconds
--force-stream Enforces a streaming contract for subscription. The StreamFeed role is used instead of Feed.
Sample: connect "dxlink:wss://demo.dxfeed.com/dxlink-ws" Quote AAPL -p dxfeed.experimental.dxlink.enable=true
Sample: connect demo.dxfeed.com:7300 Quote AAPL
"""

var subscription = Subscription()
Expand Down
51 changes: 51 additions & 0 deletions Samples/Tools/QdsTool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// QdsTool.swift
// Tools
//
// Created by Aleksey Kosylo on 05.12.23.
//

import Foundation
import DXFeedFramework

class QdsTool: ToolsCommand {
var isTools: Bool = true
var cmd = "Qds"
var shortDescription = "A collection of tools ported from the Java qds-tools."

var fullDescription =
"""
Qds
=======
Usage:
Qds <arg> [<options>]
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)")
}

}
}
3 changes: 2 additions & 1 deletion Samples/Tools/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit 0c50a94

Please sign in to comment.