Compare commits

..
885 Commits
Author SHA1 Message Date
John Colvin 259c78f067 cleanup: Remove empty file (clearly added by accident) 2024-02-08 19:04:13 -06:00
John Colvin 0dd55a26f1 cleanup: Remove superfluous 'daemon' arg check
This arg doesn't seem to have a purpose. It was prob leftover from
testing or something
2024-02-08 19:04:13 -06:00
John Colvin 63e6f69fa6 cleanup: Remove redundant 'provide_command_line' call
'Configuration.initialize' already does this
2024-02-08 19:04:13 -06:00
John Colvin 21c9a36cce cleanup: Use top level statements in PubSubServer
This is the way
2024-02-08 19:04:13 -06:00
John Colvin 7a6e9bc3c8 fix rem locator 2024-02-08 19:04:12 -06:00
John Colvin d09ed6a8dd Add more descriptive logs (via stdout) during initialization
The C++ configure/initialize routines were particularly opaque
2024-02-08 19:04:12 -06:00
John Colvin 9382807fe8 fix: Fix improper 'OfType' linq cast
Previously, animations were expressed through polymorphism (derived from the
base class CellAnimation), but the new impl uses composition. This 'OfType' call
was leftover from the polymorphism implementation, an attempt to linq cast
elements of base class (CellAnimation) to BackgroundAnimation.
2024-02-08 19:04:12 -06:00
John Colvin 131640e3d8 cleanup: Remove static service Locator class
It relied on a static singleton 'ServiceContext'. Replace references with a
properly scoped (i.e., non-static) ServiceContext
2024-02-08 19:04:12 -06:00
John Colvin 397f21a90a refactor: Reduce code (simplify) in BTS.init
Remove the 'args' parameter, since the cmd line can be obtained from
Environment.GetCommandLine anyways
2024-02-08 19:04:12 -06:00
John Colvin db90f6f7b9 Add proper cli to DataStreamPublisher
Using CommandLineParser nuget pkg
2024-02-08 19:04:12 -06:00
John Colvin c187e6ce0e check point (bc i don't trust googledrive sync yet) 2024-02-08 19:04:12 -06:00
John Colvin b6d13002d6 gitpod: Install pcap 2024-02-08 19:04:12 -06:00
John Colvin 7fdc408cf8 gitpod: Install all deps in the same 'init' cmd
Otherwise, these procs run in parallel in different terminals, which is jarring
to watch. Furthermore, installing deps in parallel stress-tests the apt package
manager, and is likely not the way it was intended to be used.
2024-02-08 19:04:12 -06:00
John Colvin 74048ec221 gitpod: Install ssh 2024-02-08 19:04:12 -06:00
John Colvin 8a14648d01 gitpod: Install lttng
For diagnostic tracepoints
2024-02-08 19:04:12 -06:00
John Colvin 4e9da4e943 gitpod: Install rapidjson
Emumba's deribit-connector lib depends on this
2024-02-08 19:04:12 -06:00
John Colvin 38b2ac362a gitpod: Install ccache 2024-02-08 19:04:12 -06:00
John Colvin dc73796987 gitpod: Activate python venv with bash script (not fish) 2024-02-08 19:04:12 -06:00
John Colvin 231bc346ae gitpod: Use docker image 'gitpod/dotnet'
This should have everything we need, including dotnet 8!
2024-02-08 19:04:12 -06:00
John Colvin 8361f33af2 gitpod: Remove unnecessary 'if' checks in init cmds 2024-02-08 19:04:12 -06:00
John Colvin 2c95a5f8b8 externals: Change repo url to use read-only access token 2024-02-08 19:04:12 -06:00
John Colvin 7e4bc590e7 dev: Fix gitpod.yml (prepend img w/ dockerhub url) 2024-02-08 19:04:12 -06:00
John Colvin 2d88ac3894 dev: Add gitpod.yml for cloud workspaces 2024-02-08 19:04:11 -06:00
John Colvin d4f02480df DataStreamCore Json stuff 2024-02-08 19:04:11 -06:00
John Colvin b0d90fc0e2 Tweak Bts.DataStream.Websocket DataSync, etc. 2024-02-08 19:04:11 -06:00
John Colvin e54628fda7 Remove unused 'JsonRpcErrorCode'? 2024-02-08 19:04:11 -06:00
John Colvin 240c4e8661 Add/modify JsonRpc stuff 2024-02-08 19:04:11 -06:00
John Colvin 1b7e54e334 Fix JsonExtensions? 2024-02-08 19:04:11 -06:00
John Colvin 55f9b3c8dc fix: Fix erroneous lock usage 2024-02-08 19:04:11 -06:00
John Colvin 30bbf9550d refactor: Add handy WebsocketExtensions
* IsSocketStateOpen
* IsClosedProperly
2024-02-08 19:04:11 -06:00
John Colvin 5c0fa54089 editorconfig: Use standard c# capitalization rules
* Use 'PascalCase' for public members (instead of 'snake_case')
* Use 'camelCase' for private members (instead of '_snake_case')
2024-02-08 19:04:11 -06:00
John Colvin 22af2d6777 build: Remove version part of RuntimeIdentifiers
This fixes a warning that arose as a side effect from upgrading to net8.0
2024-02-08 19:04:11 -06:00
John Colvin d0bed28278 docker: Fix clang-17 2024-02-08 19:04:11 -06:00
John Colvin 4fca5f4df5 docker: Install gdb (for c++ debugging)
VS Code debugger depends on this
2024-02-08 19:04:11 -06:00
John Colvin 370d84432d build: Upgrade DataStreamWebsocketClient/Server to net8.0 2024-02-08 19:04:11 -06:00
John Colvin 9f9274ae30 build: Upgrade ExpressionTests/Tester to net8.0 2024-02-08 19:04:11 -06:00
John Colvin 2590e2bbb0 docker: Remove kitware 'rc' (release candidate) apt repo
No reason to keep it. Probably shouldn't have been added in the first place
2024-02-08 19:04:11 -06:00
John Colvin c9a1c908e1 docker: Make clang-17 the default clang 2024-02-08 19:04:11 -06:00
John Colvin e6ed3931f9 docker: Install clang 17 2024-02-08 19:04:11 -06:00
John Colvin 377dafdf3b build: Upgrade c# to net8.0 (DataStreamSuite) 2024-02-08 19:04:11 -06:00
John Colvin a617227417 check pt: Before going to Chi (11/07/23, random scripts, etc.) 2024-02-08 19:04:10 -06:00
John Colvin 1fb3b88c31 check pt: Before going to Chi (11/07/23) 2024-02-08 19:04:10 -06:00
John Colvin 5ccdaae235 add util: StringStreamEnumerable 2024-02-08 19:04:10 -06:00
John Colvin 56675e3aa4 add websocket server config, README 2024-02-08 19:04:10 -06:00
John Colvin 6c139a42e3 refactor: Change WebsocketServerConfig.port to uint32
It should always be a number between 1-65535
2024-02-08 19:04:10 -06:00
John Colvin 70f8085980 feat: Add Bts.DataStream.Websocket/Server 2024-02-08 19:04:10 -06:00
John Colvin 8db13cfeb2 refactor: Add WebsocketGatewayObservable
An IObservable wrapper for IWebsocketConnectionGateway
2024-02-08 19:04:10 -06:00
John Colvin fc1ea873dd refactor: Remove nullability constraint in GetValueOrDefault 2024-02-08 19:04:10 -06:00
John Colvin 6db0306a18 refactor: Use events to avoid circular deps for ws sync/gateway 2024-02-08 19:04:10 -06:00
John Colvin 1356db8906 refactor: Let caller specify nullability of T in json parse fn 2024-02-08 19:04:10 -06:00
John Colvin 7f1ee5c363 refactor: Get rid of redundant UniversalNumericComparer 2024-02-08 19:04:10 -06:00
John Colvin 8084063976 refactor: Reorganize NumericComparer, support all types 2024-02-08 19:04:10 -06:00
John Colvin 649eca98f1 DataStreamWebApp check pt (works w/ default launchProfile) 2024-02-08 19:04:10 -06:00
John Colvin 9f9bb65eff feat: Add JsonRpc types for websocket paradigm 2024-02-08 19:04:10 -06:00
John Colvin f43e3de5bb Some ish that works (datastream webapp) 2024-02-08 19:04:09 -06:00
John Colvin 48e3cf844d Add reference to spark_api for datastream web server 2024-02-08 19:04:09 -06:00
John Colvin 914b5b5ebf docker: Update default compiler versions
Via update-alternatives
2024-02-08 19:04:09 -06:00
John Colvin 998ca2690b cleanup: Remove leftover legacy files 2024-02-08 19:04:09 -06:00
John Colvin 04721f6248 build: Upgrade c# to net8.0 (spark_websocket, Spark.Admin.WebApp) 2024-02-08 19:04:09 -06:00
John Colvin 622729bf1b docker: Upgrade dotnet 7 -> 8 2024-02-08 19:04:09 -06:00
John Colvin 5cd8ad79a3 Check pt before trip to NC 2024-01-18 2024-02-08 19:04:09 -06:00
John Colvin 133261fc41 build: Upgrade c# to net8.0 2024-02-08 19:04:09 -06:00
John Colvin 0f66ffec53 Add bones for Bts.DataStreamWebApp.Client 2024-02-08 19:04:09 -06:00
John Colvin e09debe58a Add bones for Bts.DataStreamWebApp.Server 2024-02-08 19:04:09 -06:00
John Colvin 9212c6d097 Line ending changes in yacc/lex generated code
I recently upgrade the YaccLexTools nuget to 1.2.2, perhaps these new
line endings are related to that.
2024-02-08 14:28:36 -06:00
John Colvin 8660dea85a build: Downgrade new DataStream code from net8 -> net7
The AddColumnsStream, SortStream, and requisite yacc/lex grammar were
originally added to a new branch, off of development, which is on net8.
I forgot to change it to net7 when I cherry-picked the commits for the
regular development branch.

It's wasn't quite as simple as flipping net8 -> net7 in csproj files,
because I was eager to use new language features only available in net8!
Namely, primary constructors and collection expressions.
2024-02-08 14:24:31 -06:00
John Colvin d0ddc1d57b Resurrect SortStream
Add ColumnSortExpressions grammar (lex/yacc)
2024-02-08 10:04:53 -06:00
John Colvin fe1e953030 Resurrect AddColumnStream
Add ColumnExpressions grammar (lex/yacc)
2024-02-08 10:04:53 -06:00
John Colvin dab17af5a9 build: Upgrade YaccLexTools to 1.2.2 2024-02-08 00:51:16 -06:00
John Colvin 7fb7b1e4af Fix PriceStatsStream
* Store subscription IDisposable in class (we need to control the life of the subscription)
* Flip typo '_dirty = false' -> '_dirty = true'
2024-02-04 22:14:00 -06:00
John Colvin bc5bcbf11e fix: Bootstrap MarketDataClient.price_ticker/stats w/ init state
Bugs (fixed):
  * MarketDataClient.price_ticker, and price_stats streams don't fire update
    with initial state (they only tick as subsequent changes are observed)
2024-02-04 15:33:20 -06:00
Taha Afzal 287ee291cc Adding a stream that send a TCP packet to the echo server and monitors the n_sends and n_recvs 2024-01-25 13:37:41 -05:00
Taha Afzal 2bceda01ae Added code in BlueDataUtility to create schema from data 2024-01-22 16:28:23 -05:00
John Colvin c39a270115 fix: Support all exchs in QueryServer::get_names 2024-01-17 11:15:01 -05:00
Taha Afzal 6e3f9f99c0 Merge branch 'development' of bitbucket.org:bluetradesys/spark into development 2024-01-17 10:08:17 -05:00
John Colvin b53d9d7d4c refactor: Remove 'Platform' (md source) config
Good riddance. Improper 'PlatformMap' config was often the reason market
data mysteriously wouldn't show up in the client. Especially with new
exchanges. We should keep all md source/connection configuration in one
place (one proto message), to avoid any confusion.
2024-01-17 01:42:57 -05:00
Taha Afzal cc3e289345 KeyValueToRelationalStream added 2024-01-16 19:08:40 -05:00
John Colvin 60a8b4f8c7 Gitignore all .tmp dirs (at any level) 2024-01-15 13:34:35 -05:00
John Colvin c5e0a93869 Gitignore all .venv* dirs (at any level) 2024-01-15 13:33:05 -05:00
John Colvin 3a3216421b Remove unnecessary file temp.cpp 2024-01-15 13:33:05 -05:00
Taha Afzal 8cbbbc6da3 Merging 2024-01-13 23:45:51 -05:00
John Colvin 25117c5bb7 Append application name to "logging" dir
So we can run datastream procs alongside sparkd on the same machine without
log file conflicts
2024-01-12 14:22:02 -05:00
John Colvin 8c95b43524 devcontainer: Name mount dir w/ 'devcontainerId'
To ensure it is unique on the main host (i.e., outside the container). Get rid
of devcontainer_initialize.sh, all it did was run "mkdir". Something this
trivial can be inlined in the devcontainer.json (less indirection this way).
2024-01-12 11:41:40 -05:00
John Colvin 1324e2aad1 Gitignore the '.devcontainer' dir (not the json file)
We actually do track a 'devcontainer.json' file (to keep as a template). We
just don't keep it in the '.devcontainer' dir, for the same reason we don't
track the '.vscode' dir: so devs can tailor it to their specific needs.
2024-01-12 11:41:40 -05:00
John Colvin 6fad8b754b docker: Install kitware-archive-keyring to keep key in sync (for cmake) 2024-01-12 11:41:40 -05:00
Taha Afzal f872fe9d56 AsyncTCPConnection_APM.cs now send onData with Disconnection if it detects teh other side has ShutDown 2024-01-11 17:02:41 -05:00
Taha Afzal d50e8cda50 Adding AsyncTCPConnectionAcceptor_APM and AsyncTCPConnector_APM to create ITCPConnection 2024-01-11 16:10:51 -05:00
Taha Afzal 694f8b8d11 AsyncTCPConnection_APM works now 2024-01-09 14:34:15 -05:00
Taha Afzal 047267ad1b AsyncTCPConnection_APM completed (not hooked yet) 2024-01-06 11:34:46 -05:00
Taha Afzal 5b4b41d4eb Adding MongoDB astream integration 2024-01-02 00:44:52 -05:00
Taha 3e25b4918f Adding 3 AsyncTCPCOnnections for APM, TAP, and SocketAsyncEventArgs 2024-01-02 00:43:40 -05:00
Taha Afzal 1ceea4af5a Changing TCPUtils to use SocketAsyncEventArgs instead of TAP functions, simple client<->server works with echoing messages 2023-12-20 11:32:53 -05:00
Taha Afzal cdc7da8c59 Adding sec_name col to bbo 2023-12-18 12:57:04 -05:00
Taha Afzal f1e26b984a Merge branch 'development' of bitbucket.org:bluetradesys/spark into development 2023-12-18 12:42:35 -05:00
Taha Afzal a7189628b1 Adding EMA, SMA and RenkoStreams 2023-12-18 12:42:14 -05:00
John Colvin 32433577ec fix build (client): Move a few includes inside 'if' ppd 2023-12-14 11:31:31 -05:00
John Colvin ed5ef1b7c4 fix build: Remove a few RequiresPreviewFeatures attrs
Features which are now standard in .Net
2023-12-14 11:16:19 -05:00
Mohammad Arham ac7c38d0e2 Merge branch 'development' of bitbucket.org:bluetradesys/spark into development 2023-12-13 21:06:41 -08:00
Mohammad Arham b887f90b99 added book levels to mdrecorder 2023-12-13 21:06:19 -08:00
John Colvin 9a0ef90700 fix build (windows): Update fmt to v10.1.1
Manage this dep with vcpkg now (instead of externals)
2023-12-13 13:27:29 -05:00
John Colvin 5086e81578 build: Add vcpkg as submodule 2023-12-13 12:34:14 -05:00
Mohammad Arham 2230f8d748 emty string can also be default linfopath 2023-12-11 06:49:34 -08:00
Mohammad Arham 1fa66f4815 defaults updated to make glbx work on onix 2023-12-11 06:47:49 -08:00
Mohammad Arham e5d19ceb8d assert if channerls per thread < 1 2023-12-11 06:47:03 -08:00
Mohammad Arham edda571509 added glbx config just to enable glbx 2023-12-11 06:45:36 -08:00
Mohammad Arham 55f20e5a09 Added entry for cme/onix in mdgateway 2023-12-11 06:43:05 -08:00
Taha Afzal 619b49ee6c Changing the stream subscription structure 2023-11-15 12:30:43 +00:00
Taha Afzal ab32055416 Adding C++ stream tables (and tests) 2023-11-14 21:53:54 +00:00
Taha Afzal 2ae3ded65e src/DataStreamSuite/DataStream/Primitives/FileStreams/PlaybackStream.cs 2023-11-14 18:15:53 +00:00
Taha Afzal 4acb1e268a Merging 2023-11-14 18:14:18 +00:00
Mohammad Arham d45c79c44b Merge branch 'development' of bitbucket.org:bluetradesys/spark into development 2023-11-02 07:46:49 -07:00
John Colvin cba32be99d fix build: Use relative path in csproj references
The build was broken because Spark.csproj was looking for SharedStreams
at some hardcoded path on taha's comp
2023-10-26 14:37:56 -04:00
John Colvin 292fa54dda fix: Get rid of hardcoded path to dll
Use Assembly.Location instead

Bugs (fixed):
  * PubSubServer throws an exception on startup because it can't find
    dll at hardcoded path
2023-10-26 14:31:20 -04:00
John Colvin 3b059ebdfa fix: Format arguments properly in DataStream code gen
Previously, all arguments were formatted as "Bts.DataStream.Argument"
(from the default ToString)
2023-10-26 14:24:32 -04:00
John Colvin d0d3c9de4e feat: Allow line-comments in DataStream parser
Supports c#/c++ style line comments (i.e., that begin with '//')

TODO: block comments
2023-10-26 12:59:44 -04:00
John Colvin 633163518a fix: Fix divide token typo (should be fwd slash) 2023-10-26 12:59:44 -04:00
John Colvin 0a466052e0 cleanup: Remove old submodules (again)
* docker/linux
* docker/windows
2023-10-26 10:52:15 -04:00
John Colvin 7e139ddf0a cleanup: Remove old submodule docker\linux (again) 2023-10-26 10:48:47 -04:00
John Colvin dcac260efe fix (hack): Pass lines as array to cloud stream
Rather than a single multi-line string. This hack will have to do
until we implement multi-line strings in the parser.
2023-10-25 17:42:59 -04:00
Taha 81ea106ce3 Fixing the DSQA query box font color 2023-10-23 15:18:44 -04:00
Taha 88bf04e5f1 TimeSeries and TimeBucketStreams, Stream offloading etc 2023-10-23 14:18:31 -04:00
Taha 33030b1212 Market data streams work now 2023-10-16 00:01:29 -04:00
Taha 140c0c4152 MDStream uses MarketDataClient instead of MDConsumer now 2023-10-03 18:35:23 -04:00
Taha 7d63718602 MDStream uses MarketDataClient instead of MDConsumer now 2023-10-03 18:35:23 -04:00
John Colvin 9cb94fabdb fix: Add cross-type NumericComparer for BooleanExpressions
Bugs (fixed):
   * FilterStream throws exception when comparing numeric arguments
2023-10-02 22:02:35 -04:00
John Colvin e37a39f9fc chore: Add SharedStreams to default loaded assemblies cfg 2023-10-02 21:03:54 -04:00
John Colvin 7e307504cb chore: Remove redundant reference from csproj 2023-10-02 20:53:26 -04:00
John Colvin d01809e49c refactor: Move ProtoHelper to spark_api
So it can be used by other csprojs (was previously stuck in Spark)
2023-10-02 20:45:32 -04:00
John Colvin 292ed2dc0e refactor: Convert WebsocketServerParams to proto 2023-10-02 20:45:32 -04:00
John Colvin 623fce6e8f build: Enable nullable in proto generated cs 2023-10-02 20:45:32 -04:00
John Colvin 7d6d4c03b0 build: Update IronPython to v3.4.1 2023-10-02 20:45:32 -04:00
John Colvin 4962556a6c build: Update protobuf-net to v3.2.26
Also update System.Collections.Immutable to v7.0.0 to new deps
2023-10-02 20:45:32 -04:00
John Colvin 5ad9d9a0e6 build: Update System.Reactive to v6.0.0 2023-10-02 20:45:12 -04:00
John Colvin a091a95f50 build: Add .cmd wrapper script for build_data_stream.py 2023-10-02 19:38:38 -04:00
John Colvin 0bd06da929 build: Upgrade Google.Protobuf to 3.24.3
Now all csprojs are on the same Google.Protobuf version. Previously,
DataStreamSuite projs were on this (newer) version, while Spark projs
were on 3.21.12
2023-10-02 19:38:38 -04:00
Taha af9dd0c1fe PubSub Streams to get list of tags etc 2023-10-02 19:38:38 -04:00
John Colvin fd9eaa65ed build: Add script to build DataStreamSuite and cpp deps 2023-09-30 13:54:58 -04:00
John Colvin 1c744329e5 chore: Add SharedStreams.csproj bones 2023-09-30 13:08:03 -04:00
Taha f8c9148609 Adding tests 2023-09-30 12:59:02 -04:00
Taha fa4da63c24 Streams can be published across PubSub now 2023-09-30 12:59:02 -04:00
Taha 7bb7f1a5e2 PubSub is working now 2023-09-30 12:53:51 -04:00
Taha 3fa37397d9 AsyncTCPCOnnection2 done 2023-09-30 12:52:37 -04:00
Taha d75f97ba1f Both SImpleTCPClient and SimpleTCPServer use non async calls now 2023-09-30 12:52:37 -04:00
Taha 404698152e Merging, and adding test project 2023-09-30 12:52:37 -04:00
John Colvin 9311c27f47 feat: Resurrect DataStream primitives
They were originally commented out because the expression parsing utils
weren't ready (now they are).
2023-09-29 13:10:50 -04:00
John Colvin 1dfc028554 fix (temp): Comment out TestPublisher in Program.Main 2023-09-29 13:10:50 -04:00
John Colvin 931c681174 fix build (DataStreamSuite): Change path sep to '\' in Build.targets
Csharp protobuf generation was failing, albeit inconsistently, with a
mysterious error message about normalizing relative/absolute paths.
2023-09-29 13:10:50 -04:00
John Colvin f4568c3bb7 docker: Fix typo in README 2023-09-29 13:10:50 -04:00
John Colvin 126e3571df docker: Restructure/clean up Dockerfile
Break up large RUN steps (where many apt pkgs are installed at once) to
smaller incremental ones. If 'docker build' fails on a particular RUN
step, it can be re-run from the last successful step, so smaller steps
better preserve progress.
2023-09-29 13:10:49 -04:00
John Colvin 6759ce3a2d docker: Install latest cmake & node
The versions in the default apt repo are too old (need cmake >= 3.23,
node >= 16.0.0)
2023-09-29 13:10:49 -04:00
John Colvin 300a9b4eff docker: Use ubuntu:latest instead of transient 22.10
'latest' guarentees we're on an LTS release
2023-09-29 13:10:49 -04:00
John Colvin 52bb54252d gitignore: Add *.Generated.cs, *.lst
The Yacc code generator emits these files
2023-09-29 13:10:49 -04:00
John Colvin b416209ca7 refactor: Add DataStream cfg protos
Translated from Edge config
2023-09-29 13:10:49 -04:00
John Colvin bcd8aa3d80 refactor: Return fake data from myGetAllTagsStream
Until we port the actual impl from Edge
2023-09-29 13:10:49 -04:00
John Colvin ed0be9162b refactor: Move PrimitiveManager to DataStreamCore
So DSQA can reference it
2023-09-29 13:10:49 -04:00
John Colvin 54a6dca401 chore: Clean up leftover DataStreamGrammar dir 2023-09-29 13:10:49 -04:00
John Colvin 248e37577f feat: Add DataStreamExpressions
All lex/yacc scanners/parsers are now generated with a proper dotnet
nuget pkg, YaccLexTools.

* Implements BooleanExpressionFilter with the new Parser.
2023-09-29 13:10:49 -04:00
John Colvin ac1ede5986 refactor: Move a few low-level DataStream types to DataStreamCore
So the lex/yacc generators can reference them
2023-09-29 13:10:49 -04:00
John Colvin d1f5ae86fd chore: Get rid of BooleanExpressionsInterpreter csproj 2023-09-29 13:10:49 -04:00
John Colvin 094ea67e43 feat: Impl BooleanExpressions 2023-09-29 13:10:49 -04:00
John Colvin ca95ab7a24 feat: Add ArithmeticExpressions csproj 2023-09-29 12:54:14 -04:00
John Colvin e4f276be2a refactor: Consolidate redundant HighPerformanceTimer classes
Move the one in Spark csproj to spark_core, and reference spark_core
in all the DataStreamSuite csprojs that need it.
2023-09-21 23:48:57 -04:00
John Colvin a18521674e fix: Only init static DataStreamLoadFileConfig once 2023-09-21 23:48:57 -04:00
John Colvin d366ccc9c9 fix: Add simple null check 2023-09-21 23:48:57 -04:00
John Colvin 92e4b0a793 feat: Open gui when DSQA runs 2023-09-21 23:48:57 -04:00
John Colvin 56f7518186 chore: Uncomment DataStream Primitives code
It builds now that all the deps are in place
2023-09-21 23:48:57 -04:00
John Colvin 99ff8ac8dd chore: Comment out refs to PublishedTagsStream
For the DataStream port

TODO: Port PublishedTagsStream from edge
2023-09-21 23:48:57 -04:00
John Colvin 0754b48d44 chore: Comment out refs to SitesCfg
For the DataStream port

TODO: Translate SitesCfg to protobuf to integrate w/ modern config
2023-09-21 23:48:57 -04:00
John Colvin 081e96bca6 build: Add GuiUtilities csproj
For the DataStream port (DSQA depends on this proj)
2023-09-21 23:48:57 -04:00
John Colvin 8665bfc2d2 fix build (wip): Disambiguate HighPerformanceTimer ref 2023-09-21 23:48:57 -04:00
John Colvin 725471a238 fix build: Add using System.Runtime to fix TimeSpan ref
This Windows type must have moved namespaces since the Edge days
2023-09-21 23:48:57 -04:00
John Colvin d09c6ba543 refactor: Replace outdated DataGrid refs w/ DataGridView
Windows replaced the former with the latter in dotnet core 3.1
2023-09-21 23:48:57 -04:00
John Colvin 80c4542942 refactor: Replace old BlueEventLog w/ (Spark) Log 2023-09-21 23:48:57 -04:00
John Colvin 4446eb0412 chore: Get rid of redundant DataPacket.cs 2023-09-21 23:48:57 -04:00
John Colvin 71f642aef5 chore: Progress twds building DSQA 2023-09-21 23:48:57 -04:00
John Colvin 700bc45998 chore: Add DSQA (work-in-progress) 2023-09-21 23:48:57 -04:00
John Colvin 7cc7dd652f chore: Add missing DataStreamExpression.parser(.cs) 2023-09-21 23:48:57 -04:00
John Colvin 9fdffdc648 chore: Remove redundant init calls 2023-09-21 23:48:57 -04:00
John Colvin a3406279f9 fix build: Don't inherit build props/targets in WebApp build
The Directory.Build.props/targets files were recently moved up to the
'src' dir (from 'src/client') for the new DataStreamSuite sln. Evidently
this broke the WebApp build.
2023-09-18 05:03:11 +00:00
John Colvin 3ccda24e20 fix: Add missing venue cases in AdminWebApp
Coinbase and OKX
2023-09-18 05:02:12 +00:00
John Colvin 10085a4976 fix build: Don't copy 'sparkd.lic' in cmake install tgt
This was a license file for the emumba-deribit lib. We don't need it now
that the license check has been disabled.
2023-09-17 21:20:50 +00:00
John Colvin 78f41127fe chore: Remove artifact from old web build (added by accident) 2023-09-17 20:09:59 +00:00
John Colvin 8c35d63ab8 chore: Remove empty dirs (added by accident) 2023-09-06 18:24:04 +00:00
Taha 797816be7e Merging changes 2023-09-04 16:25:40 -04:00
John Colvin c4216d2272 build: Configure DataStreamSuite cpp to only build on Windows 2023-09-03 14:16:33 -04:00
John Colvin 431dad7551 fix: Init logging/config in DataStreamPublisher entry pt 2023-09-03 14:16:33 -04:00
John Colvin 7a5025d9d9 build: Add spark_core and spark_api to DataStreamSuite sln
Although outside of the DataStreamSuite dir, they should be included
because some csprojs in the sln depend on them.
2023-09-03 13:53:07 -04:00
John Colvin cc2959249e build: Add lexer/parser.cs files to src ctrl
Move all lexer/parser files into a single dir, DataStreamGrammar, for
organizational purposes and to avoid dependency conflicts when
generating code. Note that we'll only need to regen cs if we modify the
parser/lexer files, which seems unlikely.
2023-09-03 13:53:07 -04:00
John Colvin 86a1695286 Add update-synth-strategy fn to SyntheticSecurityClient 2023-09-01 23:24:35 -04:00
John Colvin 4c1cbbe8fe build: Remove unnecessary WorkingDirectory attrs
From the GenerateLexer/Parser targets
2023-09-01 12:48:18 -04:00
John Colvin 5081153db9 fix build: Don't explicitly include generated parser/lexer cs files
Since the files are generated in the source dir (not the build dir),
they are automatically included in the build. This removes a few
warnings abt duplicate symbols.
2023-09-01 12:46:21 -04:00
John Colvin 846ed05f76 chore: Remove redundant props in nested Directory.Build.props 2023-09-01 12:40:08 -04:00
John Colvin 3e9afea40a refactor: Rename DataStream ExpressionSyntax/Parser -> Boolean
The DataStream name was causing confusion. The lexer/parser are both
part of BooleanExpressions csproj, so the Boolean name is appropriate.
2023-09-01 12:38:27 -04:00
John Colvin cfa35fb5ce fix build: Add dummy classes for DataStreamSuite 2023-09-01 01:39:15 -04:00
John Colvin 9e221cabc3 build: Add BooleanExpressionsInterpreter csproj
For the DataStream port

* Add Lexer/Parser build targets
* Update externals w/ lexer/parser generator deps
2023-09-01 01:28:40 -04:00
John Colvin 23c83c0fb6 fix: Skip 1st arg (exe-path) when parsing cmd line
This only applies to Spark.exe, where the args are obtained via
Environment.GetCommandLineArgs, rather than directly from a 'main' fn.
The former prepends the [Spark] exe path to the argv array from 'main',
which the CommandLine parser does not expect.
2023-08-29 00:31:02 -04:00
John Colvin 5368f25ed8 feat: Generate rich version w/ GitVersion.MsBuild pkg
Run one of our dotnet exes w/ '--version' to print info to console
2023-08-29 00:21:54 -04:00
John Colvin bee76289ca chore: Format csproj & fsproj files 2023-08-28 12:25:47 -04:00
John Colvin 1fcfc2886c chore: Add displayName, description to cmake preset 2023-08-24 14:40:54 +00:00
John Colvin 83c35f55a3 build: Make DataStreamSuite build cross-platform 2023-08-24 14:40:15 +00:00
John Colvin 2f9f0108ef build: Rename cmake scripts by platform client/server spec
Now that we've added another cmake preset (data-stream-suite) some
scripts (GetLinuxClient*.cmake) are shared by multiple presets.
2023-08-24 14:32:44 +00:00
John Colvin 75a1165923 build: Remove dotnet build tgt from CMakeLists
Calling 'dotnet build' from CMakeLists doesn't feel natural; it's
simpler to just run it from the cmd line, or in a script.
2023-08-24 04:22:40 +00:00
John Colvin 2d394b77f4 chore: Remove redundant flags from CMakeLists
They're already defined in CMakePresets
2023-08-24 04:22:40 +00:00
John Colvin 59e5727f71 fix build (api serv linux): Use cmake shared lib suffix var
This Makes code platform independent. The build was broken because it
 was trying to copy a ".dll" file on Linux.
2023-08-24 04:22:40 +00:00
John Colvin f5d2e98d4f fix build (api serv linux): Fix cfg in CMakePresets
The api server linux config shouldn't inherit the spark (windows)
config; no reason to tether them together.
2023-08-24 04:11:47 +00:00
John Colvin 481f33c462 fix build (api serv linux): Fix link lib typo 'fmt' -> 'fmtd' 2023-08-24 04:04:39 +00:00
John Colvin 513bbeeaae fix build (api serv linux): Revert primary ctr syntax
This is a new feat in cs lang version 12, which is only in preview mode.
Reverting the syntax change bc I couldn't get it to build on Linux.
2023-08-24 04:04:39 +00:00
John Colvin 0cade21f1d build: Remove libspark from spark_client.sln
Libspark's inclusion in the sln file has become redundant now that
its bins are copied to the dotnet build dir as part of the CMake build
process. Unlike msbuild, dotnet doesn't integrate nicely with c++. It
seems better to keep c++ projects out of the sln.
2023-08-23 02:41:35 -04:00
John Colvin 7b284b40f7 fix build: Remove problematic generator expression
Just copy libspark.dll over to the dotnet build dir for now.
TODO: additionally copy pdb file for debug builds
2023-08-23 02:39:43 -04:00
John Colvin e1b6971667 build: Greatly simplify build_spark.py
Make it a thin wrapper around dotnet/cmake clis
2023-08-23 00:46:21 -04:00
John Colvin ecbae62d07 feat: Add bones for DataStreamSuite
TODO (Taha): Migrate source files from edge
2023-08-22 15:04:08 -04:00
John Colvin 8182b4b289 dev: Simplify sparkd build instructions
Restructure in style similar to Spark and Api Server build instructions
2023-08-22 14:38:39 -04:00
John Colvin a644174601 dev: Add instructions to build spark in README 2023-08-22 14:38:39 -04:00
John Colvin cf34c13f03 build: Replace build_api_server.py w/ cmake/dotnet clis
Add instructions to build the Api Server in README
2023-08-22 14:38:39 -04:00
John Colvin 126e84e4e8 build: Remove 'jobs' arg from CMake build presets
Modern CMake uses an appropriate number of jobs by default (I believe
the number of cores on the cpu)
2023-08-22 14:38:39 -04:00
John Colvin 5ffc83a237 build: Init SPARK_ENABLE_API_SERVER reguardless of platform 2023-08-22 14:38:39 -04:00
John Colvin 3082f5c8d9 build: Only build Admin Web App on Linux 2023-08-22 14:38:39 -04:00
John Colvin f1cde451d8 build: Copy libspark to dotnet bin dirs in CMakeLists 2023-08-22 14:38:39 -04:00
John Colvin 6f0e0e5172 build: Add Spark.Api.Server to CMakePresets 2023-08-22 01:29:45 -04:00
John Colvin b2d5ab5e03 chore: Add SyntheticSecurityClient to WebsocketDataSync
TODO (Arham): Integrate SyntheticSecurityClient w/ the websocket api
2023-08-21 15:35:03 -04:00
John Colvin c3e098e27d feat: Add SyntheticSecurityClient (for websocket api) 2023-08-21 15:05:37 -04:00
John Colvin a930d2165a refactor: Move SyntheticTuple to spark_api proj
Also clean struct up a bit and rename 'SyntheticSecurityTuple'
2023-08-21 15:05:37 -04:00
John Colvin 05cdfce9ce fix: Add null checks to account for bad analytics exp params
The Spark client was throwing null ref exs after merging prod to
developement, likely because the param protos stored in db were invalid.
2023-08-11 11:42:29 -04:00
John Colvin 61c9d6b2d6 fix build: Sand rough edges after merge 2023-08-05 00:09:16 -04:00
John Colvin 7545d3fd5c Merge remote-tracking branch 'origin/spark_crypto.prod' into development 2023-08-04 13:40:04 -04:00
John Colvin 04e0297e86 refactor: Simplify 'render_piq' by using common code
No need to re-invent the 'render_cells' wheel
2023-07-31 14:50:44 -04:00
John Colvin 562706b968 fix: Don't assume ladder row-data is sorted by price
Bugs (fixed):
   * Ladder assert-crashes when rendering volume-at-price

   Cause: The render routine expected items to be sorted by price, and
   asserted as much (indirectly). In hindsight, this expectation placed
   an unnecessary burden on the caller.
2023-07-31 14:20:08 -04:00
John Colvin 4195207a71 fix: Replace non-existent StaticResource w/ BTSColor
Bugs (fixed):
   * The Activity Log window crashes immediately opened.

   Cause: WPF throws an Exception because it fails to resolve the
   StaticResources 'TextBox.BackgroundBrush', and
   'TextBox.ForegroundBrush', as they are defined in Colors.xaml, which
   is not imported by LogViewer.xaml.

   I replaced the StaticResources w/ BTSColor extension (rather than
   include Colors.xaml), because it is less error prone, and allows us
   to keep colors organized in 1 place: BTSColors.cs.

   I'm not sure how long the bug was around. It likely slipped through
   the cracks because the ActivityLog window isn't used often.
2023-07-28 14:16:46 -04:00
John Colvin 71eb89b6a1 fix: Check 'HasQuantityDisplay' before accessing prop
Bugs (fixed):
   * The PNL Summary window throws a null ref ex when the first row is
     populated.

     Cause: The SecurityMetadataImmutable's internal QuantityDisplay is
     null. In other words, the mutable SecurityMetadata obj around which
     it wraps has a null QuantityDisplay, which is not allowed since
     Immutable protos (such as 'QuantityDisplayImmutable') must be
     constructed w/ a non-null instance of their mutable counterpart.

* Implement same fix (pre-emptively) in ManualFillRow, and
  OrderCompletedEventPredicate.
2023-07-28 14:01:57 -04:00
John Colvin 94e4a0b725 fix: Change bus data type to nullable immutable
Bugs (fixed):
   * The InterpTheosServerPublisher throws a null ref during startup when it
     accesses 'UsageList' from the VolSurfaceUsageTag data.

     Cause: Immutable protos instantiated w/ the default ctr have an
     invalid state, because the mutable (reference type) instance around
     which they wrap is null. Since an immutable type's props are trivial
     wrappers for this mutable instance, they throw a null ref if the
     mutable instance is null.
2023-07-28 12:02:50 -04:00
John Colvin 40d1fe20e3 diag: Add detailed error logs to notification serv order handler
Maintain a circular buffer of the last N updates. Then if/when an
exception occurs, log the update sequence that led up to it.
2023-07-26 15:30:55 -04:00
John Colvin 2ed23159ca style: Clean up jenkins build script
* Get rid of double backslashes in quoted paths to improve readability
* Call 'activate.bat' instead of 'activate' (official python docs say to
  use the former)
* Add docs
2023-07-26 15:26:30 -04:00
John Colvin faa8438adf build: Make jenkins build script independent of working dir
This alleviates an unneccessary burden on callers (previously, it had to
be run from the repo root dir).
2023-07-26 11:59:03 -04:00
John Colvin 0b35c2ccde fix: Add lock, try/catch in notification serv order handler
Brandon has been experiencing a crash on startup. The stack trace shows
this handler is throwing a duplicate-key ex on 'dictionary.Add' (unclear
why).
2023-07-26 00:55:50 -04:00
John Colvin 98eea0ef09 chore: Remove unused iface member 2023-07-26 00:13:22 -04:00
John Colvin 4bf237aebe fix (pre-emptive): Guard against null/empty prices in LadderRender 2023-07-25 14:27:13 -04:00
John Colvin da927adef4 fix: Check price is within ladder's range before rendering
Bugs (fixed):
  The render routine was indirectly asserting that each item's price was
  >= the ladder's min price. That seems like an inappropriate burden to
  put on the caller. Now we filter these items out in the routine.
2023-07-25 14:24:16 -04:00
John Colvin cf587e26d5 fix: Remove bad assert abt tickdiff in LadderRender
* The test condition was wrong in the first place
* Instead of assert/crashing, log a warning
2023-07-25 14:22:15 -04:00
John Colvin 9e4354fb55 fix buid: Don't goto ERROR just bc venv already exists
This seems like a typo
2023-07-18 23:40:18 -04:00
John Colvin e6bb4c73a8 fix build (jenkins): Upgrade pip via 'python -m pip'
For some reason 'pip install --upgrade pip' works on my laptop, but fails on
the Jenkins box.
2023-07-18 22:53:32 -04:00
John Colvin e43a2a4818 build: Add build script for new Jenkins (on aws) 2023-07-18 22:25:56 -04:00
John Colvin cde0f44b7d build: Default to Release cfg for 'publish' target 2023-07-18 22:25:06 -04:00
Taha b07a1e2c74 Fixing the issues, where the theos are only published out by the vol surface owner 2023-07-18 20:40:59 -04:00
Taha Afzal 8376fce5fe Merge branch 'spark_crypto.prod.vol_order' into spark_crypto.prod 2023-07-14 17:01:29 +00:00
Taha Afzal d9e5c846c2 Adding more logs to VolAlgo 2023-07-14 16:57:55 +00:00
Taha Afzal 65736c13ef VolAlgo completed 2023-07-14 03:54:14 +00:00
Taha Afzal 071c28e925 VolAlgo reflects its state correctly now 2023-07-10 03:20:05 +00:00
Taha Afzal 8355e3e1be VolAlgo code complete - need to test 2023-07-09 04:21:42 +00:00
John Colvin f9a6e0963c chore: Remove Spark.Admin.WebApp
These files were added by accident (leftover from switching branches
from development -> spark_crypto.prod)
2023-07-06 14:52:57 +00:00
John Colvin b2879837c6 chore: Remove devcontainer.json 2023-07-06 12:26:48 +00:00
John Colvin 0d03ddb009 Merge remote-tracking branch 'origin/spark_crypto.prod' into spark_crypto.tick_hotfix 2023-07-06 12:26:28 +00:00
John Colvin a6dfa4ae80 fix: Don't show decimal BTC Futs/Spd qtys
They tick in multiples of 10, so decimal precision isn't needed
2023-07-05 18:20:53 -04:00
John Colvin e66ec82ba8 hotfix: Setup default cfg for new Deribit price ticks 2023-07-05 18:19:49 -04:00
John Colvin 9ce5e971c6 fix: Fix typos in BTSColor paths in xaml 2023-07-05 18:11:40 -04:00
John Colvin 3e7cc49ebb hotfix: Format text w/ RegionalTickFactors in PriceEntryControl 2023-07-05 18:11:40 -04:00
John Colvin d07e68b6e2 hotfix: Use 1st leg's min price tick rule for Deribit combos 2023-07-05 18:11:40 -04:00
John Colvin 619ece2313 refactor: Consolidate impl for 'round_to_tick' overloads
Also add a 'decimal' overload for RegionalTickFactors. This is more work
for Deribit tick hotfix.
2023-07-05 18:11:40 -04:00
John Colvin 1dda9566f3 hotfix: Use '.' separator if tick unit is multiple of base 2023-07-05 18:11:06 -04:00
Taha 3704d1ed16 InterptheosServerPublisher is now opulated the newly added vol field in the PrecomputedTheoPoint proto 2023-07-05 14:41:31 -04:00
John Colvin a524ca02a5 refactor: Change tick arithmetic to use int64
The tick count is "price / tick_size" and tick_size is usually < 1, so
the extra bits may be needed to avoid arithmetic overflow
2023-07-05 12:02:28 -04:00
John Colvin 3c97f2552b fix build: Don't use libfmt or ranges in win cpp
I can't deal with this anymore. My build is suddenly broken on Windows
(for spark_crypto.prod branch). I assume they updated the compiler
in a way that isn't backwards compatible. Thanks Windows.
2023-07-05 11:58:14 -04:00
John Colvin 15b1d55ef1 fix build: Disable Binance md code on win 2023-07-05 11:58:14 -04:00
John Colvin 4e42c9f01b test: Refactor tick tests for RegionalTickFactors
Gives us some peace of mind about the dynamic ticks hotfix for Deribit
2023-07-05 11:58:14 -04:00
John Colvin 76775f821a hotfix: Support dynamic ticks in order ticket 2023-07-05 11:58:14 -04:00
John Colvin e7088f6b1c hotfix: Support dynamic ticks in ladder
Deribit now provides dynamic price ticks (a list of ticks per range).

https://www.deribit.com/kb/4-july-2023
https://www.deribit.com/kb/deribit-on-screen-options-tick-size-reduction
2023-07-05 11:58:14 -04:00
Taha Afzal f2c3ff4be6 Adding vol to PrecomputedTheoPoint 2023-07-05 15:16:45 +00:00
Taha 1fb42ade59 Adding perf logs on the front end 2023-07-05 10:50:13 -04:00
Taha 129650e9d4 Only the skew owner publishes theos to the server 2023-07-05 10:50:13 -04:00
John Colvin 170a44ac04 fix: Check sign to tick in correct direction
Don't assume it's positive and blindly tickup
2023-07-03 22:34:46 -05:00
Taha Afzal 7e04f02327 Merge branch 'spark_crypto.prod.autofit' into spark_crypto.prod 2023-07-04 03:21:28 +00:00
Taha Afzal abda2dbf97 VolSurfaces and achived theo history size is not mantained at runtime 2023-07-04 03:13:46 +00:00
Taha Afzal ad1a45cf49 ArchivedTheos are truncated on a server start 2023-07-04 03:13:46 +00:00
John Colvin e9abdd0ff2 chore: Remove unused fn 'gen_prices' 2023-07-03 12:30:03 -05:00
John Colvin 9254002318 fix: Check HasPrice/QuantityDisplay before accessing prop 2023-07-03 12:24:20 -05:00
John Colvin 596780b7f4 chore: Remove unused 'unit_quantity' prop 2023-07-03 12:22:37 -05:00
John Colvin 7ba061ac20 hotfix: Add cfg to account for new deribit tick format 2023-07-02 16:58:53 -05:00
John Colvin f8e6b73714 fix: Add missing venues to switch statement 2023-06-26 17:34:52 +00:00
John Colvin c01593d119 fix (ui colors): Cherry-pick synth editor dark theme from dev 2023-06-26 12:26:38 -04:00
John Colvin dd53c149c0 fix: Fix typo in default cfg 'SPOT' -> 'SECURITY_TYPE_SPOT' 2023-06-26 15:39:47 +00:00
John Colvin 04b4efe1e1 Update externals
Addresses more trivial build errors after upgrading to C++ 20
2023-06-26 15:24:46 +00:00
John Colvin 81bafbe68d fix build: Address trivial werrors after upgrading to C++ 20
All werrors were about implicit 'this' captures in lambdas
2023-06-26 15:24:46 +00:00
John Colvin 7ee95c55ab build: Upgrade CLI11 to v2.3.2 2023-06-23 15:35:06 +00:00
John Colvin 87d67feff4 build: Upgrade (Linux) c++ to stdlib 20 2023-06-23 15:33:40 +00:00
John Colvin d21ceddbb6 build: Upgrade (Windows) c++ to stdlib 20 2023-06-23 15:33:40 +00:00
John Colvin 4434df3d09 fix: Account for duplicate sec keys in 'normalize_drivers' 2023-06-23 15:33:40 +00:00
John Colvin 35916881c8 fix: Invalidate 'My Windows' module content on open (hover)
Bugs (fixed):
  * My Windows module popup is always empty

    Cause: The list of favorite windows is only evaluated on startup
    (before the list has been properly initialized). Furthermore, even
    if the list was initialized, it must be re-evaluated to account for
    newly added/removed windows.
2023-06-23 15:33:40 +00:00
John Colvin 5230d6bab5 build: Clean up build_spark.py 2023-06-23 15:33:40 +00:00
John Colvin 68c3418c04 build (refactor): Upgrade libfmt from ~8.0.1 to 10.0.0 2023-06-23 15:33:40 +00:00
John Colvin 7bce9f8a7f fix: Fix typo 'groups' -> 'currencies' 2023-06-21 11:07:47 -04:00
John Colvin a5b988738f chore: Add 'requests' module to py venv
This module is used to download files. It is required for the new
'install_fmt.py' script in externals.
2023-06-21 11:07:47 -04:00
John Colvin 53a4b61884 chore: Remove unused cmake var 2023-06-21 11:07:47 -04:00
John Colvin 7be111dc36 refactor: Use upper case http method name in ccapi params 2023-06-21 11:07:47 -04:00
John Colvin 0c5bd66cca refactor: Improve logging sec parsing logs (binance futs) 2023-06-21 11:07:47 -04:00
John Colvin b699c5a310 refactor: Simplify json impl w/ macros 2023-06-21 11:07:46 -04:00
John Colvin af8850f4c0 fix: Gracefully handle REQUEST_STATUS msgs (from ccapi) 2023-06-21 11:07:46 -04:00
John Colvin 10e359d6b5 refactor: Remove unnecessary template param 2023-06-21 11:07:46 -04:00
John Colvin b360881b8b chore: Impl 'descriptor' switch case for all exchs 2023-06-21 11:07:46 -04:00
John Colvin b250dc31d3 chore: Subscribe to BTC/USDC currencies in deribit md cfg 2023-06-21 11:07:46 -04:00
John Colvin 995df189ae chore: Add OKX to symbols.conf 2023-06-21 11:07:46 -04:00
John Colvin 93739e7010 improvement: Show Venue/SecType names in logs (not numeric val) 2023-06-21 11:07:46 -04:00
John Colvin bc42498d61 fix build: Disable ccapi/ftx
It appears that ccapi's ftx execution management code is broken (not that
it really matters, bc it's ftx). We prob should have already disabled this
disgraced exchange anyways.
2023-06-21 11:07:46 -04:00
John Colvin 2b95507c49 build: Better organize CMakeLists per-platform/project 2023-06-21 11:07:46 -04:00
John Colvin ca8c3a18d7 build: Generate only necessary cs files for protos
Prior to this commit, proto files were added to csprojs via the Proto3
target. This target generated 4 files per proto:
  .cs, .immutable.cs, .client.pb.cs, and server.pb.cs
For the (many) proto files that don't define services (just normal messages),
the .client/server.pb.cs files were unnecessary.

This commit splits proto-generation into 2 targets:
  * ProtoService - same as the old 'Proto3' target (generates 4 files per
    proto as described above).
  * Proto - a new target that generates only .cs, and .immutable.cs files
2023-06-21 11:07:46 -04:00
John Colvin e49066ffa7 fix build: Fix cacheVariables in CMakePresets 2023-06-21 11:07:45 -04:00
John Colvin e3cd910acd build: Use CMakePresets in build_spark.py 2023-06-21 11:07:45 -04:00
John Colvin cb47177b8e build: Remove unused 'link_build_dir' arg 2023-06-21 11:07:45 -04:00
John Colvin fba00c9d51 fix build: Remove unused fn 'notnulld'
This fn broke the Spark release build due to an '#if DEBUG' ppd
2023-06-21 11:07:45 -04:00
John Colvin af0b7d9146 fix build: Set cmake policy CMP0076 before target_sources
* Removes warning when configuring build on Windows
* Moves 'vs_filters.cmake' to 'cmake' dir (w/ other cmake scripts)
2023-06-21 11:07:45 -04:00
John Colvin e0a8c476f6 build: Increase sparkd parallel jobs to 8 2023-06-21 11:07:45 -04:00
John Colvin 5acb8100de devcontainer: Define env var 'XDG_CONFIG_HOME' 2023-06-21 11:07:45 -04:00
John Colvin 1c133e87e7 Update externals to get ccapi v5.45.2 2023-06-21 11:07:45 -04:00
John Colvin 8a8419576d build: Add 'Debug (ccapi diag)' configuration preset
Simply a clang debug build w/ ccapi log level set to 'Trace' (instead of
'Debug')
2023-06-21 11:07:45 -04:00
John Colvin 4a28723adb chore: Organize ccapi compile defs in CMakeLists 2023-06-21 11:07:45 -04:00
John Colvin e482408f29 fix: Add 'notional' filter class to model binance md json 2023-06-21 11:07:45 -04:00
John Colvin 4dcc98ab1f improvement: Check for empty str when parsing numbers (json) 2023-06-21 11:07:45 -04:00
John Colvin ace0fc35a2 refactor: Don't log error in Price::from_json
These logs get noisy fast
2023-06-21 11:07:45 -04:00
John Colvin c7d1eb00dc refactor: Add TimeSpan, TimeStamp arithmetic 2023-06-21 11:07:45 -04:00
John Colvin 949c8e0a32 build: Enable boost-beast for ccapi 2023-06-21 11:07:45 -04:00
John Colvin c2419b491a fix: Ensure ccapi log filenames aren't deallocated
Logs are committed asynchronously, and since ccapi log filenames are
passed by value, we must store them somewhere
2023-06-21 11:07:45 -04:00
John Colvin 786322f397 feat: Add Okx md (ccapi) 2023-06-21 11:07:45 -04:00
Taha 09e2a1764f Only the user with control over the volsurface can save it 2023-06-15 11:44:34 -04:00
John Colvin a780668bce fix: Ensure tick up/down values are within min/max bounds 2023-06-15 11:43:58 -04:00
John Colvin 5b79aeaa14 ui: Enforce min auto-fit period (30 secs) 2023-06-15 11:37:18 -04:00
John Colvin 049c006b5f ui: Disable driver/atm pts moved auto-fit ui 2023-06-15 11:37:18 -04:00
John Colvin 6fdc344472 feat: Add 'acquire ownership' button to vs context menu 2023-06-15 11:37:18 -04:00
John Colvin cb09b93553 chore: Rename ns bts.reactive -> Spark.Core.Reactive 2023-06-15 11:37:18 -04:00
John Colvin 21447d32e5 fix (vs ui): Only log 'is_dirty' changes for editable cols 2023-06-15 11:37:18 -04:00
Taha 28b03e1cd2 Only the user with control over the volsurface can save it 2023-06-14 22:23:45 -04:00
Taha a7acb89c15 Fixing merge conflict 2023-06-14 15:57:42 -04:00
John Colvin 35289710ba fix: Ensure tick up/down values are within min/max bounds 2023-06-14 14:20:47 -04:00
Taha 4677acfb39 Merge branch 'spark_crypto.prod.autofit' of bitbucket.org:bluetradesys/spark into spark_crypto.prod.autofit 2023-06-14 13:55:03 -04:00
Taha ac05d0d69e AutoFitter reads the settings from the settings now 2023-06-14 13:54:53 -04:00
John Colvin 25a9b6b433 fix: Ensure tick up/down values are within min/max bounds 2023-06-14 13:49:49 -04:00
John Colvin b78713ad0d ui: Enforce min auto-fit period (30 secs) 2023-06-14 12:59:40 -04:00
John Colvin 1f3d0e879c ui: Disable driver/atm pts moved auto-fit ui 2023-06-14 12:59:39 -04:00
John Colvin baad4dc68e feat: Add 'acquire ownership' button to vs context menu 2023-06-14 12:22:57 -04:00
John Colvin ef7c0c7a30 chore: Rename ns bts.reactive -> Spark.Core.Reactive 2023-06-14 11:39:06 -04:00
Taha 3b3c4a2a35 Merge branch 'spark_crypto.prod.autofit' of bitbucket.org:bluetradesys/spark into spark_crypto.prod.autofit 2023-06-14 10:21:55 -04:00
John Colvin ef9fc66a31 fix (vs ui): Only log 'is_dirty' changes for editable cols 2023-06-14 09:44:42 -04:00
John Colvin 212d9c853b fix: Init auto fit vals in vs settings editor 2023-06-14 09:09:34 -04:00
Taha 7815b18b6b Merge branch 'spark_crypto.prod.autofit' of bitbucket.org:bluetradesys/spark into spark_crypto.prod.autofit 2023-06-13 22:34:12 -04:00
Taha 05126074d4 Enabling AutoFit 2023-06-13 22:34:07 -04:00
John Colvin 3611d2c1f3 fix: Enable tick up/down buttons for nullable uint32 ctrl 2023-06-13 15:43:33 -04:00
John Colvin b5ad4b8104 feat: Add auto-fit ui for vs settings 2023-06-13 15:43:33 -04:00
Taha 43d7c0a2b5 Comments 2023-06-12 13:43:42 -04:00
Taha 12e361cec7 AutoFit based on a timer works now 2023-06-11 21:59:46 -04:00
John Colvin a4b0f026f4 style: Don't use implicit ptr -> bool conversion
Check 'ptr == nullptr' instead.
2023-06-07 13:16:22 -04:00
John Colvin 59f65c32d8 refactor: Change if/else blocks to switch expression 2023-06-07 13:16:22 -04:00
John Colvin ccec77f7d1 refactor: Fix typo 'uitilities' -> 'utilities' 2023-06-07 13:16:22 -04:00
John Colvin 1deeb85d22 improvement: Filter Deribit instrument reqs by regex cfg 2023-06-07 13:16:21 -04:00
John Colvin 648a32147a refactor: Eliminate SecurityID dependency on JsonReader
It's a fundamental type, included by many source files. The fewer
dependencies the better.
2023-06-07 13:16:21 -04:00
John Colvin 806ddfc156 Update externals so ccapi Deribit sends heartbeats 2023-06-07 13:16:21 -04:00
John Colvin 05b5f22204 fix: Capture cfg by value in thread lambda
Bugs (fixed):
  * A race crash occurs during startup, seems related to starting emumba
2023-06-07 13:16:21 -04:00
John Colvin 4f09d2cff1 refactor: Move Emumba deribit cfg to own proto 2023-06-07 13:16:21 -04:00
John Colvin e1234fe583 fix: Fix typo in log helper script 'show_last_run.sh'
So it actually applies the 'num_lines' override arg
2023-06-07 13:16:21 -04:00
John Colvin aa64dacd65 fix: Abort '_add_spread' if any leg secs missing
Bugs (fixed):
  * Sparkd crashes occassionally during startup. The last logs suggest
    it is related to adding Deribit spreads to shared mem.
2023-06-07 13:16:21 -04:00
John Colvin 10b062ebce fix build: Fix typo in CMakePresets cfg profiles 2023-06-07 13:16:21 -04:00
John Colvin e057057173 chore: Add replay/recording cfg to md_dev/prod profiles 2023-06-07 13:16:21 -04:00
John Colvin 82cec2672a fix build: Fix typo in Venue enums in default confs 2023-06-07 13:16:21 -04:00
John Colvin 50184cd6ff docker: Add hostRequirements, shm to devcontainer
The shm-size should be more than sufficient for general market data (the
default size of 64MB wasn't cutting it)
2023-06-07 13:16:21 -04:00
John Colvin e64dc49a64 fix build: Respect cfg path order in gen'd defaults
The path order represents the value-inheritance hierarchy. This way,
values from files earlier in the path take precedence over those from
later files.
2023-06-07 13:16:21 -04:00
John Colvin 010bd53723 fix: Include 'id' member in equals impl 2023-06-07 13:16:20 -04:00
John Colvin 50ae7ca7f9 feat: Add Deribit md (ccapi) 2023-06-07 13:16:20 -04:00
John Colvin 995bbef878 refactor: Add currencies to SecurityCriteria proto 2023-06-07 13:16:20 -04:00
John Colvin 8c325e30be improvement: Validate SecurityCriteriaClause proto
To ensure 'SecurityCriteriaClause::include' calls are reasonably cheap
2023-06-07 13:16:20 -04:00
John Colvin 6bb9b24210 feat: Add 'name_regexps' to SecurityCriteriaClause
This will allow us to filter out securities (instruments) at Deribit
(and likely other venues) BEFORE requesting their metadata. This
will be particularly useful when reacting to instrument state changes
(i.e., when a new instrument is added), which occur one instrument at
a time, and only provide the instrument's name.
2023-06-07 13:16:20 -04:00
John Colvin df1c558c33 refactor: Shorten SecurityCriteriaClause var names
* Drop 'security_' prefix (considering the class name, it is redundant)
* Change 'descs' -> 'names'
2023-06-07 13:16:20 -04:00
John Colvin 357d245a4c fix: Use JsonReader::read rather than nlohmann::get
The former is a more robust solution (logs exceptions, primitive string
conversion, etc.)
2023-06-07 13:16:20 -04:00
John Colvin d43863ab59 refactor: Change BoolName cstrings to strings 2023-06-07 13:16:20 -04:00
John Colvin 89188acc7d refactor: Define 'fmt' fns for a few md types 2023-06-07 13:16:20 -04:00
John Colvin 86a9fc0c83 chore: Add 'fmt' impl for domain::Security
This allows us to pass domain::Security to the LOG macro.
2023-06-07 13:16:20 -04:00
John Colvin 15579acd2a fix build (web): Add missing Venue switch cases 2023-06-07 13:16:19 -04:00
John Colvin 411009c996 Update externals to get ccapi v5.45.1 2023-06-07 13:16:19 -04:00
John Colvin 17a4cce68b refactor: Change 'Currency' from enum to string
It is an unnecessary burden to ensure the enum represents the union set
of currencies available at all suppported venues. The benefits of using
an enum are slim to none (it is practically unreferenced in code), so
the burden isn't justified.
2023-06-07 13:16:19 -04:00
John Colvin adb36795a8 chore: Rename a few .conf files to snake case 2023-06-07 13:16:19 -04:00
John Colvin 691545b71a refactor: Remove redundant sec type field
The Security class already has a 'type' fn that treats the type as a
function of the security variant. This is better than the 'type' field
in SecurityCommon, because it's naturally in sync with the variant.
2023-06-07 13:16:19 -04:00
John Colvin 31c7fa4f2c fix (pre-emptive): Return 'UNSPECIFIED' if sec-type variant empty 2023-06-07 13:16:19 -04:00
John Colvin 86009c3cdb refactor: Reduce Binance US dependency on Binance
There is some common code, but it seems like a good idea to keep
exchange-specific md impls modular/independent
2023-06-07 13:16:19 -04:00
Taha Afzal c9392dd306 Adding multiple accounts to CCAPIExecutionGateway 2023-06-06 18:30:38 +00:00
Taha Afzal ac8a6094fb Cleaning up corrid generation 2023-06-06 18:30:38 +00:00
Taha Afzal 6dbe497013 Bug fixes 2023-06-06 18:30:38 +00:00
Taha Afzal 274aa9b17d Error on order entry handled 2023-06-06 18:30:38 +00:00
Taha Afzal d47e61ca57 CCAPISingleOrderManager state machine fixed 2023-06-06 18:30:38 +00:00
Taha Afzal 3078b918d2 CLeaning up 2023-06-06 18:30:38 +00:00
Taha Afzal 95e9a6e8aa Sending RFQs now (combo creation not done) 2023-06-06 18:30:38 +00:00
Taha Afzal 1a3cf1dbea OpenOrders are reported bck now 2023-06-06 18:30:38 +00:00
Taha Afzal 0d705eed1f PositionRequest cleaning up and consolidating multiple messages (corresponding to different currencies) into one 2023-06-06 18:30:38 +00:00
Taha Afzal 1d28526792 Querying Positions and passing them to the client now 2023-06-06 18:30:38 +00:00
Taha Afzal 3ecf3dd048 OpenPositions and WorkingOrders queried from Deribit now 2023-06-06 18:30:38 +00:00
Taha Afzal 64ff79a38d Passing config to connection config to CCAPIDeribitOrderMux 2023-06-06 18:30:38 +00:00
Taha Afzal aba478f3dc Adding meaningful correlation ids 2023-06-06 18:30:38 +00:00
Taha Afzal 1025881ec8 Stable CCAPI based Deribit execution using per instrument subscription - improvements needed 2023-06-06 18:30:38 +00:00
Taha Afzal 6d95a645e3 Deribit's option position request hooked up 2023-06-06 18:30:38 +00:00
Taha Afzal 4769f66eea Adding some logs to SharedMemory and SharedList 2023-06-06 18:30:38 +00:00
John Colvin 82c126362d fix build: Fix a few path errors in publish target 2023-05-31 22:13:52 -04:00
Taha fd2ba70031 Culling the logs 2023-05-29 11:35:49 -04:00
Taha ab410c339f Order Tickets from the sheets are defaulted correctly now 2023-05-29 10:32:29 -04:00
Taha Afzal 9093c72646 Merge branch 'temp_arham' into spark_crypto.websocket-api.ccapi 2023-05-09 03:56:35 +00:00
arhamGIT 3a220b8320 Merge branch 'temp_arham' of bitbucket.org:bluetradesys/spark into temp_arham 2023-05-08 23:40:44 -04:00
arhamGIT ac20f7c9dd front end changes to make coinbase work 2023-05-08 23:40:28 -04:00
Taha Afzal 578146905e coinbase working 2023-05-09 03:31:20 +00:00
arhamGIT 7f07f5a69b Merge branch 'temp_arham' of bitbucket.org:bluetradesys/spark into temp_arham 2023-04-26 12:33:50 -04:00
arhamGIT 3dd7d0999e merge 2023-04-26 12:33:32 -04:00
Taha Afzal 5076770d15 coinbase sec names showing in shrd mem 2023-04-26 16:27:34 +00:00
Taha Afzal 791446c514 changed to merge proto updates 2023-04-25 15:38:37 +00:00
Taha Afzal 66370bd541 Merge branch 'spark_crypto.websocket-api.ccapi' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api.ccapi 2023-04-24 23:24:25 +00:00
Taha Afzal cce8973e87 temp changes to make binance work 2023-04-24 23:19:15 +00:00
John Colvin 37dcd32c6b fix (cli): Fix config --query output indentation
There are 2 spaces per indent level
2023-04-20 00:46:23 -04:00
John Colvin d772958272 diag: Show file/line in Config logs 2023-04-20 00:46:23 -04:00
John Colvin c85e221e9f build: Automatically run build_spark.py in venv 2023-04-20 00:46:23 -04:00
John Colvin 28e95df5c6 refactor: Rename 'STOCK' -> 'SPOT' 2023-04-20 00:46:23 -04:00
John Colvin 8d84355d57 chore: Add Binance BTC qty formatting to default conf 2023-04-20 00:46:23 -04:00
John Colvin 5c25f9a3e5 refactor: Rename Venue/SecType enums according to conventions
https://protobuf.dev/programming-guides/style/#enums
2023-04-20 00:46:23 -04:00
John Colvin c0980809c5 chore: Format .conf files
* Indent with 2 spaces
2023-04-20 00:46:23 -04:00
John Colvin e946c6427e chore: Rename Ports.conf -> ports.conf
This is consistent with proto file naming conventions recommended by
Google (snake_case)
2023-04-20 00:46:23 -04:00
John Colvin 58ccbe2b19 chore: Consolidate default md conf into one file 2023-04-20 00:46:22 -04:00
John Colvin 7519c0b63a build: Update dotnet fable to 4.0.6 2023-04-20 00:46:22 -04:00
John Colvin 947c071cee build: Remove unused cmake def 2023-04-20 00:46:22 -04:00
John Colvin 54018fcce7 refactor: Clean up 'PlatformLoader'
* Rename 'SymbolLoader'
* Consolidate complicated filter logic into one 'load' overload

refactor: Get rid of unnecessary PlatformConfig
2023-04-20 00:46:22 -04:00
John Colvin 4b85eb33f8 chore: Remove redundant Symbols.conf file 2023-04-20 00:40:56 -04:00
John Colvin 592cf54e94 chore: Remove irrelevant test for config fallback url
The 'fallback url' was removed from config a few months ago (this test should
have been removed with it)
2023-04-20 00:40:56 -04:00
John Colvin b8368bf9fa chore: Remove unused args/code
* Removes several 'if' blocks whose predicates were effectively compile-time
  constants (i.e., unnecessary).
2023-04-20 00:40:50 -04:00
John Colvin 7d19ea84ab chore: Remove redundant fn 'get_thread_name' 2023-04-18 23:57:24 -04:00
John Colvin 14651341c4 fix: Fix 'Replace' fn so it ONLY replaces val if key exists
Bugs (fixed):
  * Spark (client) crashes anytime an order is canceled. Other changes
    to existing orders can cause the crash as well, but cancelling does
    so every time.

  * Cause: The IObservable<Update<T, TKey>> 'Naggle' ext fn was broken.
    Specifically, the KeyedValueCollection.Replace fn that 'Naggle' uses
    was broken. Instead of only replacing values with existing keys, it
    would add new keys as well.
2023-04-18 10:36:46 -04:00
John Colvin 681fbc6915 fix: Add 'spot' to sec type filter for preset algos 2023-04-18 00:12:46 -04:00
John Colvin 37d7f51d19 fix: Fix color-name typo in xaml 2023-04-17 23:53:51 -04:00
John Colvin 48eb0a2c9b fix: Use qty display settings in order ticket bbo header 2023-04-16 12:53:04 -04:00
John Colvin 6d2cd54deb fix: Init config w/ (optional) server arg in cli 2023-04-16 00:29:31 -04:00
John Colvin 2ec956b430 fix: Normalize cfg url path sep to '/' on Windows
Bugs (fixed):
  * All client config overrides are ignored (even the '-configserver'
  cli arg). Config overrides on the server appear to work, but they
  aren't forwaded to the client.

  Cause: cURL doesn't like the Window's path separator '\'
2023-04-16 00:13:42 -04:00
John Colvin 4f22ae04fe diag: Add verbose logs during config init 2023-04-16 00:13:42 -04:00
John Colvin 7da82d8444 cli (spark): Add 'sparkd' opt, integrate w/ CommandLineParser
This replaces the old '-configserver' arg, which will continue to be
supported for backwards compatabilty.
2023-04-14 15:16:32 -04:00
John Colvin d8611536ee fix build script: Fix venv path 2023-04-14 15:16:32 -04:00
John Colvin c94ffd1a56 cli: Add spark.console.cmd (alias for Spark.Console.exe) 2023-04-14 15:16:32 -04:00
John Colvin cddf081e19 fix (cli): Read %~dp0 before SHIFT
I just discovered that, when SHIFT is run (the first time), the value of
%~dp0 changes from the script's parent dir to the current working dir
2023-04-14 13:18:28 -04:00
John Colvin 94071b4889 refactor: Move Spark cmd opts to own file 2023-04-14 13:18:28 -04:00
John Colvin d7518cffe1 fix: Don't round ccapi book qtys to int 2023-04-14 17:07:25 +00:00
John Colvin fa26ecaf67 fix: Fix typo 'BINANCE' -> 'BINANCE_US' 2023-04-14 17:07:25 +00:00
John Colvin c2eaf00aaa improvement (cli): Add spot & option to sec type choices 2023-04-14 17:07:25 +00:00
John Colvin 74be3ec9b9 improvement (cli): Dump md json via nlohmann/json
This is much easier to read than previous json format, which we
generated ourselves, though a bit more verbose.
2023-04-14 16:55:29 +00:00
John Colvin 967e3100d2 fix (cli): Fix shared mem dump path 2023-04-14 16:55:29 +00:00
John Colvin b1d1243eae refactor: Change lib::domain::Book qty type to float 2023-04-14 16:55:29 +00:00
John Colvin 72edd99cb0 chore: Get rid of old/unused code from Spartan 2023-04-14 16:55:29 +00:00
John Colvin a512460396 diag: Log when quickbus starts/stops
Something is broken wrt port config on sparkd, and possibly spark
(client) as well. This might help track down the bug.
2023-04-14 16:54:17 +00:00
John Colvin 48ff593c2e chore: Remove unused fns
Also stop exporting PlatformLoader type since it isn't used outside of cpp
2023-04-13 13:59:14 +00:00
John Colvin d8fc99bca4 chore: Remove CMakeDeps that were accidentally added back 2023-04-13 13:59:13 +00:00
Taha Afzal 6a04759fe8 Merge branch 'spark_crypto.websocket-api.ccapi' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api.ccapi 2023-04-12 10:28:44 -05:00
Taha Afzal 2cc07b71bd Added some documentation to order_flow.txt 2023-04-12 14:21:27 +00:00
Taha Afzal 40bf117f6c Execution config fixed 2023-04-12 02:34:37 +00:00
Taha Afzal 20209ef429 Merge branch 'spark_crypto.websocket-api.ccapi' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api.ccapi 2023-04-11 16:38:47 +00:00
Taha Afzal c30a7a29fd Merging sim_execution 2023-04-11 15:34:20 +00:00
Taha Afzal c6ae2ea038 temp changes to make ws work 2023-04-11 14:16:40 +00:00
Taha Afzal f95715beec Merge branch 'spark_crypto.websocket-api.ccapi' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api.ccapi 2023-04-10 15:57:38 +00:00
Taha Afzal 0e85f4b9d5 Merge branch for 'spark_crypto.websocket-api.linux' into spark_crypto.websocket-api.ccapi 2023-04-10 15:55:46 +00:00
John Colvin ab78ae867a dev: Add docs for building/intellisense in VS Code
TODO: Add docs for building Spark on Windows
2023-04-10 11:55:13 -04:00
John Colvin 5e60f38b9b build: Change CMakePresets build/install dirs to historic paths
<build|install>/<clang|gcc>/<debug|release>
2023-04-10 11:10:37 -04:00
John Colvin 8f4b4be6db build: Fix CMakePresets build
Also drop 'spark_' in 'spark_admin_web_app_bundle' target. It's just too
long
2023-04-10 11:10:37 -04:00
John Colvin 696195aefd docker: Rename repo 'bluetradingsystems/sparkd-dev'
The previous name, 'johncolvin/bluetradingsystems', was chosen in a
misguided effort to adhere to a naming convention recommended by Docker
Hub (https://docs.docker.com/docker-hub/repos/create/). In hindsight,
this convention isn't well suited to our use case. Our images are shared
by multiple users (e.g., sparkd dev users all use the same sparkd-dev
image), so it doesn't make sense to name the repository after an
arbitrary user.
2023-04-08 12:18:39 -05:00
John Colvin 36f0a544e9 fix (pre-emptive): Include <map> in header that uses std::map
The build wasn't broken, so any deps on members that use map must have
included 'map' themselves
2023-04-08 00:52:23 -04:00
John Colvin f23242b18c improvement: Only prepend venv to PATH once per shell
Even if build_spark.cmd is called repeatedly from the same shell. This
prevents PATH from growing too long (w/ repeating venv path entries)
2023-04-08 00:46:07 -04:00
John Colvin 75dd6d659b chore: Remove old config defaults dir 2023-04-08 00:07:29 -04:00
John Colvin a23d8228b4 chore: Remove unused spark_server.sln 2023-04-07 23:58:24 -04:00
John Colvin 59f3d54597 docs: Fix typo in readme 2023-04-07 23:57:44 -04:00
John Colvin 8b3166582d refactor: Rename run_spark.cmd -> spark.cmd, add build-type arg 2023-04-07 23:55:12 -04:00
John Colvin fd13316b8e dev: Add c_cpp_properties.json and README for intellisense on win 2023-04-07 12:14:49 -04:00
John Colvin 5991ab03ec Removing docker/windows submodule (was accidentally added back) 2023-04-07 12:14:49 -04:00
John Colvin b9bc6184d4 diag: Add sym/type/exch to invalid sec channel log 2023-04-07 12:14:49 -04:00
John Colvin aab3e836c3 fix: Add Spot -> Stock sec type conversion switch case 2023-04-07 12:14:49 -04:00
John Colvin ed0fc60900 build: Clean up build_spark.py a bit 2023-04-07 12:14:48 -04:00
John Colvin 6764ae268e Removing docker/linux submodule (was accidentally added back) 2023-04-07 12:14:48 -04:00
John Colvin 6d3d9ddacf fix build: Fix merge errors (mostly trivial stuff) 2023-04-07 12:13:44 -04:00
Taha ccd76ec284 Symbols.conf 2023-04-06 21:48:34 -04:00
Taha Afzal d52ea0e997 Adding macro to stop MarketDataConfigUtils from building into windows 2023-04-07 01:41:06 +00:00
John Colvin 15e23fe486 fix: Remove 'run_emumba' from md/Run.cpp
MarketDataGateway manages emumba/deribit connections now

Bugs (fixed):
  * An spdlog exception is thrown because the run_emumba thread spawns a
    2nd emumba_logger.

    Cause: The first emumba logger is spawned by the EmMDListener
    instantiated in MarketDataGateway. We shouldn't be starting emumba
    connections in 2 places.
2023-04-06 15:26:19 -04:00
John Colvin d9e5b11026 fix: Disable MDPublisher thread (at least for now) 2023-04-06 15:07:46 -04:00
John Colvin 21c19c94c2 fix: Fix typo in config defaults 2023-04-06 14:58:59 -04:00
John Colvin c31d9d6c72 Merge remote-tracking branch 'origin/spark_crypto.dev' into spark_crypto.websocket-api.linux 2023-04-06 14:44:22 -04:00
John Colvin a7e89b075b Merge remote-tracking branch 'origin/spark_crypto.ccapi' into spark_crypto.websocket-api.linux 2023-04-06 12:55:53 -04:00
arhamGIT c0bb26e56f Merge branch 'spark_crypto.websocket-api.linux' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api.linux 2023-04-06 08:36:12 -04:00
arhamGIT 1e3e57b990 misc color changes 2023-04-06 08:35:46 -04:00
John Colvin f50430e9e2 fix: Fwd ports in start_docker script 2023-04-06 00:02:53 -04:00
John Colvin 4891250959 docs: Add directions to create container from terminal 2023-04-06 00:02:53 -04:00
John Colvin ad1b89ff88 docs: Add links to dev container docs in README 2023-04-05 23:50:38 -04:00
John Colvin 49053d31c2 chore: Remove docker build script
It's just as easy to run the docker build cmd manually
2023-04-05 23:05:50 -04:00
John Colvin 651ebdbb41 docs: Remove unnecessary sample code in README 2023-04-05 23:04:03 -04:00
arhamGIT 0b50d5b5f0 dark theme in create synthetic 2023-04-05 13:52:45 -04:00
John Colvin 9e3f16d8bc fix build: Update externals so prod builds in new docker 2023-04-05 11:45:24 -04:00
John Colvin a3f194d708 build (web): Upgrade web build to net7.0 2023-04-05 11:39:37 -04:00
John Colvin d21de803f6 docker: Check if aliases.fish exists before sourcing it 2023-04-04 23:52:10 -04:00
John Colvin bb81151392 docker: Remove unused opt from build script 2023-04-04 23:52:10 -04:00
John Colvin 2b277b84a2 docker: Improve devcontainer_post_create.sh
* Create fish config dir if it doesn't exist
* Ensure git is run from a dir inside the repo
* Add basic logs
2023-04-04 23:52:10 -04:00
John Colvin 2bf4502d06 docker: Add set_user/start_docker scripts
Leave the image's default user as 'root' so we can modify the non-root user's
uid/gid. This is a common technique used in containers to gain file permissions
in mounted dirs.

The default user's uid/gid can't be changed because a bash process runs under
their ownership as long as the container is up. A user's uid/gid cannot be
changed while that user owns a process (at least not via 'usermod').
2023-04-04 23:52:10 -04:00
John Colvin 94d1b9d784 improvement: Fwd ports in devcontainer, don't stop on close 2023-04-04 00:30:04 -04:00
John Colvin ceee66d5f2 fix build: Add compile def 'SHARED_MEMORY_PREFIX' for win build 2023-04-03 19:30:14 -04:00
Taha Afzal 2e9a968752 Merge branch 'spark_crypto.websocket-api.linux' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api.linux 2023-04-03 11:14:30 -05:00
John Colvin 6c2989b139 refactor (docker): Replace usermod cmds w/ opts in 'useradd' 2023-04-03 11:52:19 -04:00
John Colvin 6c2bfee616 fix (docker): Set default user without specific group
Bugs (fixed):
  * The default user does not have sudo permission in the container,
    unless the user is specified explicitly in the 'docker exec' cmd
    (via -u <user>).

    Cause: When the default user is specified with a specific group
    (in this case, its namesake 'bts'), it is excluded from all other
    groups, including 'sudo'.
2023-04-03 11:43:37 -04:00
John Colvin 30c5ea7fb2 chore: Name devcontainer scripts after associated json prop 2023-04-03 10:49:58 -04:00
John Colvin a6831b5548 chore: Add devcontainer.json to bootstrap devcontainers 2023-04-03 10:49:58 -04:00
John Colvin b42943fe8d chore: Rename Docker image 'spark-dev' -> 'sparkd-dev'
This is a more accurate and appropriate name than 'spark-dev' because
the image is designed to build/run Sparkd and the Spark Api Server (both
of which are daemons, hence the appropriateness of the 'd' suffix). It
isn't designed to build/run the front-end desktop application, Spark.
2023-04-03 10:28:51 -04:00
John Colvin 06c833e96c fix: Use correct prefix in md cleanup
Bugs (fixed):
  * Assert crash in MDSource.h "Marketdata heartbeats are bad..."

  Cause: The MD cleanup procedure, which is supposed to delete md files
  from shared memory (from previous runs), wasn't deleting anything.
  The file globbing pattern it was using (to determine which files to
  delete) never produced any matches because it had the wrong prefix. As
  a result, market data would often be loaded with a stale heartbeat
  timestamp from a previous run.

  Note: This occurred as a side effect of making the shared memory prefix
  configurable when we ported the api server over to Linux (so the api
  server and sparkd could run on the same container/machine whilst
  maintaining independent shared memory files).
2023-04-03 10:28:51 -04:00
John Colvin 9aff02b225 chore: Remove unused docker scripts 2023-04-03 10:28:51 -04:00
John Colvin 4229a523a8 docker: Init devcontainer bashrc and config.fish 2023-04-03 10:28:51 -04:00
John Colvin 82e9e6b6bf docker: Change default docker_user to "bts"
This way we can all use the same dev image. It also means one less
variable in our containers that paths/scripts need to account for.
VS Code can automatically update the remote user's uid in the container
to avoid permission issues in mounted dirs.
2023-04-03 13:48:43 +00:00
John Colvin 904a6db1d0 fix: Add Mercury default conf
The quickbus was essentially broken when running on the 'default'
defaults, for lack of a better word, because the ingoing/outgoing queues
in BrokerProxy would be initialized with size 0.
2023-04-03 13:48:16 +00:00
John Colvin 2a9f03741e chore: Move docker files into main repo
Changes to Docker-related files/configuration don't occur in a vacuum.
They are made in coordination with changes to the main repository, so it
doesn't make sense to track them separately.

Note: Removing the 'windows' Docker files completely. No one has has
used them in a long, long time. The client build would be broken in
there anyways, the image is based on .NET Framework 3.5!
2023-04-03 13:48:16 +00:00
John Colvin fd3de056c1 style (cli): Clean up 'key-code' cmd
* Rename 'key-code' -> 'key' (better grammar for the sub cmds)
* Rename 'key-gen' -> 'gen'

Now the 'key' cmds are 'sparkd key gen/encrypt/decrypt'
2023-03-31 05:00:07 +00:00
John Colvin 978a1e8566 dev: Integrate Docker w/ VS Code devcontainers
Hopefully this resolves all of the trouble/confusion in setting up
sparkd Docker containers
2023-03-31 04:59:58 +00:00
Taha Afzal 36e1771579 Merge branch 'spark_crypto.websocket-api.linux' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api.linux 2023-03-28 16:05:06 -05:00
John Colvin 0d23fd50f5 improvement: Indent protos in sparkd config cmd
So proto values are indented relative to the key, which is the type name
2023-03-28 10:45:03 -04:00
John Colvin 367c9c1c7c chore: Include metrics.h in MDSource.h
This file was broken, as it defines methods that depend on metrics.h.
However, the build wasn't broken because references to such methods
are in files that happen to include metrics.h themselves.
2023-03-28 00:45:07 -04:00
John Colvin 78f5526ce7 refactor: Add spark_test, Spark.Console to Spark.Api.Server sln 2023-03-28 00:45:07 -04:00
John Colvin a1d7ebd260 improvement: Lower 'finit_spark_lib' log level to Diag 2023-03-28 00:45:07 -04:00
John Colvin 3fda1cb369 improvement: Add null check for rule_desc in cfg lookup
It is possible rule_desc is null given an inappropriate field_name arg
2023-03-28 00:45:07 -04:00
John Colvin 2c2a68022b improvement: Spruce up 'config' cli
It's naturally a bit messy because we expose the c++ cli to csharp, so
it can be invoked via Spark.Console (cs) or sparkd
2023-03-28 00:45:07 -04:00
arhamGIT bb321926bc names wkng in subs, examples working 2023-03-27 11:40:51 -05:00
John Colvin 45c35ba1b2 fix build: Fix install path issues in cmake 2023-03-26 13:44:25 -04:00
John Colvin 77c61d5e3f fix build: Run dotnet tool restore when building webapp 2023-03-26 13:44:25 -04:00
John Colvin 12962ed5ca Update docker/linux, and externals
* Fixes a few build dep issues
* Adds [docker] user in container, rather than image
* Automatically installs emumba libs when creating/starting new docker
  containers
* Binds sparkd ports to the host so containers don't need to share the
  host's network stack (allows us to run sparkd in containers in WSL)
* Adds flag to start_docker.sh to allow mounting existing dirs
* Improves start_docker.sh help text
2023-03-26 13:44:22 -04:00
John Colvin f472db002c feat (sparkd cli): Bring back 'web' cmd 2023-03-25 11:46:23 -04:00
John Colvin 6939f32f69 refactor: Rename 'web' -> 'Admin.WebApp' in CMakeLists 2023-03-25 11:43:29 -04:00
John Colvin 0107d934e5 fix: Resolve req paths correctly in Admin WebApp 2023-03-25 11:00:45 -04:00
Taha Afzal ce9880a9b1 changed samples 2023-03-21 12:44:43 -04:00
Taha Afzal 317f17d7da added examples 2023-03-21 12:39:58 -04:00
Taha Afzal 7da128da6b removed allow all headers 2023-03-21 01:16:02 -04:00
Taha Afzal f603866860 changed config to make on titan 2023-03-21 01:14:56 -04:00
John Colvin dc2d525955 fix build: Reorder link libraries
For some reason, it the previous order of link libs caused an unresolved
external symbol related to open ssl (looks like a version macro)
2023-03-20 13:26:44 -04:00
John Colvin e97335189a refactor: Rename Spark.Admin.Console -> WebApp
This is a more appropriate name (it is a web app after all), especially
now that we've renamed sparkcmd -> Spark.Console (a literal console
app). The old name implies a parallel between the two apps that doesn't
exist.
2023-03-20 13:26:44 -04:00
John Colvin 81ce58268f improvement: Clean up Spark.Console
* Reword cli verbs, opts, and help text
* Rename files, folders, and namespaces
* Run code formatter
2023-03-20 13:26:44 -04:00
John Colvin 7dace3fc1d refactor: Rename sparkcmd -> Spark.Console
This is a more conventional name for a companion console app
2023-03-20 13:26:44 -04:00
John Colvin f4794bea33 improvement: Add sparkd (config-server) opt to configcheck cli 2023-03-20 13:26:44 -04:00
John Colvin b044ff3b2a chore: Transcribe more proto2 defaults to .conf files
After upgrading to proto3
2023-03-20 13:26:44 -04:00
John Colvin cd7856c46e fix build (spark): Add DeploymentType proto to spark_core 2023-03-20 13:26:44 -04:00
John Colvin 3be0ee6072 refactor: Move LazyObservable to Spark.Core.Reactive 2023-03-20 13:26:44 -04:00
John Colvin 198d26fda1 refactor: Move ObservableExtensions to Spark.Core.Reactive 2023-03-20 13:26:44 -04:00
John Colvin 8b26ac4456 chore: Remove unused code 2023-03-20 13:26:44 -04:00
John Colvin d6f172e953 refactor: Move KeyedValueSet to Spark.Core.Collections
Also rename to 'KeyedValueCollection'
2023-03-20 13:26:44 -04:00
John Colvin 91ee9b739a refactor: Move ChangeDictionary to Spark.Core.Collections 2023-03-20 13:26:44 -04:00
John Colvin b568128180 improvement: Set sys cfg build_type to release (if not debug)
For completeness sake
2023-03-20 13:26:44 -04:00
John Colvin 53a87530ee refactor: Remove erroneous 'qualifier' field from SystemConfig 2023-03-20 13:26:44 -04:00
John Colvin 450de301a9 build: Generate tsconfig file in the build dir
It never should have been dumped in the source directory in the first
place.
2023-03-20 13:26:44 -04:00
John Colvin 462b0f4eda build: Get rid of redundant py CMake utils 2023-03-20 13:26:44 -04:00
John Colvin 17402ce94a refactor: Replace os::bts_data_path w/ SystemConfig::data_path 2023-03-20 13:26:44 -04:00
John Colvin b7fae8a6f5 fix: Init quickbus node cfg w/ proper defaults 2023-03-20 13:26:44 -04:00
John Colvin 4058a98290 refactor: Rename .conf files w/ snake_case
To be consistent w/ corresponding .proto files
2023-03-20 13:26:44 -04:00
John Colvin 06d7693ed6 fix: Set hardcoded defaults for quickbus cfg
Remove these hardcoded vals once config defaults have been properly
refactored
2023-03-20 13:26:44 -04:00
John Colvin 2b01f3d902 fix: Ensure shared mem block size isn't 0 2023-03-20 13:26:44 -04:00
John Colvin d231ee50b7 chore: Fill in tedious defaults for jetfix cfg 2023-03-20 13:26:43 -04:00
John Colvin 815546d5ab fix build: Link appropriate libs for api server build 2023-03-20 13:26:43 -04:00
John Colvin 3fda0e4427 build: Add api server (dotnet) build tgt to CMakeLists 2023-03-20 13:26:43 -04:00
John Colvin a1eec029ac build: Only add sparkd related tgts if BUILD_SPARKD is true 2023-03-20 13:26:43 -04:00
John Colvin 2bbe92dbab build: Add option to enable/disable building docs
We only need to build the docs for proper releases
2023-03-20 13:26:43 -04:00
John Colvin b3d0040faa build: Replace CMAKE_BUILD_TYPE refs w/ generator expressions
To support multi-config generators (e.g., Ninja MultiConfig)
2023-03-20 13:26:43 -04:00
John Colvin c3e924be17 build (sparkd): Build server_layout target by default
The 'server_layout' was recently excluded from the default build target,
'all', because it depends on sparkd. The was done so we could optionally
configure cmake to build libspark without sparkd, as the new websocket
api server only depends on the former.
2023-03-20 13:26:43 -04:00
John Colvin dc5574e660 build: Use generator expression in tsconfig path
This is the modern CMake way. It makes the code cleaner, and supports
multi-config generators
2023-03-20 13:26:43 -04:00
John Colvin 5c19b391b1 chore: Add 'bin' dir to gitignore
The IDE (vscode) generates a 'bin' dir in the Spark.Admin.Console proj.
Presumably, this happens because the out dir is specified as a command
line arg, rather than defined in a proj file, as is the case w/ the
Spark client build.
2023-03-20 13:26:43 -04:00
John Colvin 79cb3162f2 build: Stop tracking CMakeDeps files
Not sure why these files were tracked in the first place, but cmake
automatically detects changes to the source file glob. Perhaps they were
originally added because it didn't work on some older version of CMake.
2023-03-20 13:26:43 -04:00
John Colvin e49254356a chore: Update 'tsconfig.g' path in .gitignore
Should've done this when the 'src/web' was renamed 'Spark.Admin.Console'
2023-03-20 13:26:43 -04:00
John Colvin 3192ef5561 build: Link cmake out dir to dotnet out dir
So dotnet intellisense knows where to find generated source files
2023-03-20 13:26:43 -04:00
John Colvin 8158bcb4f3 fix: Remove symlink reguardless of source path's existence 2023-03-20 13:26:43 -04:00
John Colvin b03cb94d60 build: Fix typo in msbuild prop 2023-03-20 13:26:43 -04:00
John Colvin 0f968c65b6 Fix client build after porting api server to linux 2023-03-20 13:26:43 -04:00
John Colvin 6b92773e87 build: Add quiet_exec.sh to build deps
This script probably won't ever change. Nevertheless, it is a dependency
of the admin console build.
2023-03-20 13:26:43 -04:00
John Colvin 870e1b7301 build: Use webpack mode equiv for debug/release build types 2023-03-20 13:26:43 -04:00
John Colvin 477a2f6da3 build (refactor): Rename build_web -> build_admin_console 2023-03-20 13:26:43 -04:00
John Colvin 85fe84406d chore: Clean up build_web.py a bit 2023-03-20 13:26:43 -04:00
John Colvin e8096a4db9 refactor (build): Consolidate web build into Spark.Admin.Console sln 2023-03-20 13:26:43 -04:00
John Colvin e68e673835 refactor (build): Remove redundant CWD class 2023-03-20 13:26:43 -04:00
John Colvin 53274e865a fix (pre-emptive): Fix CWD pop_path default value
In Python, default param values are evaluated once (not each time the fn
is called). This meant that, unless 'pop_path' was explicitly specified
in the CWD ctr, it wasn't necessarily the current working directory.
2023-03-20 13:26:43 -04:00
John Colvin 64df20cb36 refactor: Remove unused config-fallback path
This seems to have been here since the dawn of Spark. It is only
initialized via the -ConfigFallback option in the sparkd cli, an option
that no one ever uses (the cli provides no documentation for it either).
2023-03-20 13:26:43 -04:00
John Colvin 1977ad8ad4 build (web): Upgrade web build to net7.0 2023-03-20 13:26:43 -04:00
John Colvin a7e63d02e9 refactor: Use 'preferred_separator' when normalizing path
So callers don't have to provide the platform-dependent separator arg
2023-03-20 13:26:43 -04:00
John Colvin 593be8d069 diag: Log error on login fail 2023-03-20 13:26:43 -04:00
John Colvin f7e173f902 refactor: Enable MDConsumerInterop for api server build 2023-03-20 13:26:43 -04:00
John Colvin 7eefae4c42 diag: Add config logs
This may be temporary, but we should keep them until we know the new
proto3 configs are solid
2023-03-20 13:26:43 -04:00
John Colvin 7bb0951169 feat: Add dump-books/securities cmds to api server cli 2023-03-20 13:26:43 -04:00
John Colvin 787fb879d2 refactor: Make TickUtils public 2023-03-20 13:26:43 -04:00
John Colvin c23dafcb89 refactor: Overload subscription fns w/ filter delegate
Makes the impl more robust, as there is no reason the filter must be
tied to a specific type of filter object
2023-03-20 13:26:43 -04:00
John Colvin 111278b63b refactor: Make SecurityCriteriaExtensions public 2023-03-20 13:26:43 -04:00
John Colvin 2008478378 fix (pre-emptive): Fix typo (check val == 1, not 0)
Bugs (fixed):
   The IObservable.StopAfter ext fn never actually stops the sequence
   (even after the timeout expires).
2023-03-20 13:26:43 -04:00
John Colvin d5de60bc21 refactor: Move TableFormatter into spark_core 2023-03-20 13:26:43 -04:00
John Colvin 76172d0a5f fix: Align first item with others in TableUpdate description 2023-03-20 13:26:43 -04:00
John Colvin 1893df1f5c improvement: Lookup key rather than iterate through items 2023-03-20 13:26:43 -04:00
John Colvin a07fa26bfe fix: Pass BlitUserSymbol by val to cpp
This is a csharp/cpp interop method. The csharp delegate, which is passed
to and eventually invoked from cpp, accepts this param by value already,
but for some reason the corresponding cpp delegate accepts that same
param by ref. While working to enable the api server build on Linux, I
discovered this delegate was receiving bogus data from cpp. The problem
went away when I changed the cpp delegate param to be passed by value,
rather than ref.
2023-03-20 13:26:43 -04:00
John Colvin 41447067a2 fix: Pass non primitive args by ptr in native interop 2023-03-20 13:26:43 -04:00
John Colvin 1dd3d39a21 fix: Add nullcheck in FlattenTableSeries 2023-03-20 13:26:43 -04:00
John Colvin 4f772a1d57 build: Don't explicitly set GENERATED True for gen'd protos
CMake does this automatically now (as of version 3.20). Also, for some
reason unbeknownst to me, cmake doesn't clean the generated proto files
when they are explicitly marked as such.
2023-03-20 13:26:43 -04:00
John Colvin 97bd49d221 fix (py): Ensure 'PathOrNone.path' is actually Path or None 2023-03-20 13:26:43 -04:00
John Colvin b4374cec6b build: Add script to build api server 2023-03-20 13:26:43 -04:00
John Colvin 7e5c1218a3 build: Make app-data, shared mem paths configurable via CMake
This allows sparkd and the api server to run simultaneously in the same
docker, w/ independent data (on disk)
2023-03-20 13:26:43 -04:00
John Colvin 475970659c fix: Rename Logging.conf lowercase to match .proto
Now that we run csharp on Linux, case sensitivity matters
2023-03-20 13:26:43 -04:00
John Colvin e0706dde01 refactor: Move DeploymentType cfg to its own file 2023-03-20 13:26:43 -04:00
John Colvin 986ea74e63 fix: Call Enumerable.FirstOrDefault explicitly in overload
Bugs (Fixed):
  * StackOverflow ex is thrown in EnumerableExtensions.FirstOrDefault
    (custom overload by us) when the 'predicates' param is empty

   Cause: Our FirstOrDefault overload was calling itself (recursively),
   rather than System.Linq.Enumerable.FirstOrDefault
2023-03-20 13:26:43 -04:00
John Colvin fa0e6f7c10 fix: Get rid of 'Press any key to cancel' prompt
Console.Read throws an exception when running on linux. Furthermore, the
process can still be killed w/ ctrl+c so this doesn't remove any
functionality.
2023-03-20 13:26:43 -04:00
John Colvin ea5156122c refactor: Init ServiceContext & login outside of data sync
The login process is asynchronous, so it doesn't really fit in the
(synchronous) 'WebsocketDataSync.init' fn. This also reduces some state
in WebsocketDataSync, which is always a good thing, as it makes the
ServiceContext member readonly, and allows it to assume the user is
already logged in.
2023-03-20 13:26:41 -04:00
John Colvin 97b974a31f refactor: Clean up ServiceContext a bit 2023-03-20 13:23:49 -04:00
John Colvin ef98682620 refactor: Add IServiceProvider interface to Spark.Api
Designed to resemble Microsoft's well-known interface,
System.IServiceProvider
2023-03-20 13:23:49 -04:00
John Colvin d70eb158c4 build: Upgrade Google.Protobuf to v3.21.12 2023-03-20 13:23:49 -04:00
John Colvin 6fc34e922a build: Remove unused msbuild Item Proto3Excel 2023-03-20 13:23:49 -04:00
John Colvin fe65554c7a build: Add linux/windows OS conditions to msbuild props 2023-03-20 13:23:49 -04:00
John Colvin 78d9b678a8 build: Consolidate Proto3 output paths to OutDir & CSName
Unf, CSName is necessary because protoc converts .proto filenames to
TitleCase when generating .cs files. The other generated files
(client.pb.cs, server.pb.cs and immutable.pb.cs) don't have this problem
because they are generated with our own custom plugin.py, which gives us
control over the generated filename.
2023-03-20 13:23:49 -04:00
John Colvin 88302c9470 build: Upgrade TargetFramework to net7.0
We've been using several net7.0 preview features for a while now. Now that a
stable net7.0 release is available, it is time upgrade officially. This also
aids the effort to build csharp on Linux, where these preview features didn't
work out of the box. Lastly, trying to make these preview features work would
be a waste of time, as namespaces/interfaces in the official release have
changed in a way that isn't backwards compatible w/ the preview features.
2023-03-20 13:23:49 -04:00
John Colvin ac6c9e5c46 fix: Fix typo (make prop static) 2023-03-20 13:23:49 -04:00
John Colvin b1de323151 build: Use lower case exts in msbuild Directory.Build files
This is necessary now that we are building csharp on Linux, where, unlike
Windows, paths are case-sensitive.
2023-03-20 13:23:49 -04:00
John Colvin 24e57872ce build: Add Spark.Api.Server sln
This sln contains the csprojs needed to run the websocket api server on
linux. Like the spark_client sln, it also depends on libspark.
2023-03-20 13:23:49 -04:00
John Colvin ddd3f301b3 chore: Remove obsolete proto messages 2023-03-20 13:23:49 -04:00
John Colvin 7007fc9d6b chore: Remove obsolete proto option 'cc_enable_arenas' 2023-03-20 13:23:49 -04:00
John Colvin 7ca407fc42 chore: Translate proto2 default vals to .conf files
All proto2 config was just upgraded to proto3, which doesn't support
default values
2023-03-20 13:23:49 -04:00
John Colvin 5217e8801e Update externals to get new proto v21.12 (windows) 2023-03-20 13:23:48 -04:00
John Colvin ddd50cd916 build: Remove unused build prop 'protogen'
This was only needed to generate proto2 csharp classes, which were all
just upgraded to proto3
2023-03-20 13:23:48 -04:00
John Colvin 9ae3ababfa build: Remove proto2 target/props from cs build
Don't need them now that all cfgs have been upgraded to proto3
2023-03-20 13:23:48 -04:00
John Colvin 753cac0e7a refactor: Make proto-generated c# classes public
Two partial class defs are generated per proto. While the 'main' def was
already public, the shorter one in 'immutable.cs' was not.
2023-03-20 13:23:48 -04:00
John Colvin 6c3c9ebbcb refactor: Convert ui cfg to proto3 2023-03-20 13:23:48 -04:00
John Colvin 3aaa25a3e8 refactor: Convert toggles cfg to proto3 2023-03-20 13:23:48 -04:00
John Colvin 3fc0bce1de chore: Remove unused file 2023-03-20 13:23:48 -04:00
John Colvin fdb4544cb5 refactor: Convert various proto2 cfgs to proto3 2023-03-20 13:23:48 -04:00
John Colvin f5741d8095 refactor: Convert system/logging cfg to proto3 2023-03-20 13:23:48 -04:00
John Colvin 539d1cfeae build: Add option to use clang-13 explicitly 2023-03-20 13:23:48 -04:00
John Colvin c1ed79757c Upgrade linux protobuf from 3.19 -> 4.21.12 2023-03-20 13:23:48 -04:00
John Colvin c37727f482 Update externals to get emumba-deribit v3.3.1 2023-03-20 13:23:48 -04:00
John Colvin b25cd39481 fix build (linux): Update externals to support clang13, gcc12
Fixes the Release build (Debug was okay)
2023-03-20 13:23:48 -04:00
arhamGIT 5f93bed074 order update working 2023-03-20 16:13:50 -04:00
John Colvin bf87c46fcd fix build: Remove inappropriate ThreadStatic attr
This has likely been incorrect for a while. The problem surfaced after
upgrading to net7.0, as the new framework emits a warning (CA2259) when the
attribute is associated with a non-static field.
2023-03-07 16:30:59 -05:00
John Colvin 222d4b266e build: Disable warning cs8981
This is a new warning, introduced in net7.0, that disallows lowercase
class names. Our spark_crypto.prod branch currently uses protoc v3.19.1,
which is incompatible with this new warning, as it generates
classes with lowercase names. We can re-enable the warning when we
upgrade protoc to 3.21.12 (this has been done in the api server branch).
2023-03-07 16:25:21 -05:00
John Colvin d593eaf058 build: Upgrade TargetFramework to net7.0
We've been using several net7.0 preview features for a while now. Now that a
stable net7.0 release is available, it is time upgrade officially. This also
aids the effort to build csharp on Linux, where these preview features didn't
work out of the box. Lastly, trying to make these preview features work would
be a waste of time, as namespaces/interfaces in the official release have
changed in a way that isn't backwards compatible w/ the preview features.
2023-03-07 16:17:39 -05:00
arhamGIT ef9502c81b order entry working 2023-03-03 17:17:23 -05:00
arhamGIT 4b2c2de990 id changed to string 2023-03-02 10:32:08 -05:00
arhamGIT 79dc76c5df added entry point for taha 2023-02-28 10:14:28 -05:00
Taha Afzal eaa6493ce1 Deribit production markets can work with SimExecution 2023-02-27 20:54:43 -05:00
Taha Afzal 9fd0df2a13 SimExecution can be turned on from config now 2023-02-27 15:44:58 -05:00
arhamGIT fdbc64dfc5 basic order(lim/mark/ib) entry/deletion working 2023-02-27 13:45:45 -05:00
Taha Afzal d272612c6c Removed SimExecutionGateway's dependency on MDClient 2023-02-26 23:04:08 -05:00
Taha Afzal 77408c8c5e Fixed Self matching 2023-02-26 22:29:10 -05:00
Taha Afzal 09958eb333 SimExecutionGateway can not reflect the trades permenantly in the books 2023-02-24 11:06:26 -05:00
Taha Afzal fdb7bbdac2 SimExecutionGateway can now deal with books with 0 qty levels 2023-02-23 15:51:36 -05:00
Taha Afzal a7f24e84e4 Fills are now generated for SimExecutionGateway 2023-02-23 14:21:07 -05:00
Taha Afzal 7e5c71f337 SimExecutionGateway almost working 2023-02-23 13:43:09 -05:00
arhamGIT 62c20c96b4 forgot one file from last commit 2023-02-21 09:21:55 -05:00
arhamGIT 6b491ec209 strig list working 2023-02-21 09:16:43 -05:00
arhamGIT d009deea0e added list comprehension 2023-02-20 09:15:41 -05:00
Taha Afzal bed6feae3f Simplified SimExecutionGateway by combining order actions and matching into one 2023-02-19 00:49:30 -05:00
Taha Afzal d508d34a3a Completed books/order matching tests for SimExecutionGateway 2023-02-14 23:17:49 -05:00
Taha Afzal 5904bab03e Fixing bug with order crossing market in SimExecutionGateway 2023-02-14 16:21:57 -05:00
Taha Afzal fc9519cde3 Tests completed for working orders in the book (for SimExecution) 2023-02-14 10:06:53 -05:00
Taha Afzal 2dc823a6ac Added all the stateless book/order matching functions, and a few test cases 2023-02-13 20:09:47 -05:00
arhamGIT 390d901463 hooked subscriptions up 2023-02-13 11:50:27 -05:00
Taha Afzal ae9366f44a Adding comments and cleaning SimExecutionGateway 2023-02-12 21:27:54 -05:00
Taha Afzal db344656e5 Adding matching logic to SimExecutionGateway 2023-02-09 22:45:58 -05:00
Taha Afzal ac31deed5b Fixed Jetfix conf, and added some logs to SimExecutionGateway 2023-02-08 14:08:38 -05:00
John Colvin a0bd207d93 feat (internal): Add price stats to md client 2023-02-08 00:33:10 -05:00
John Colvin d62f88691c feat (internal): Add price ticker to md client 2023-02-08 00:23:41 -05:00
John Colvin b7c018b664 chore: Remove generated csproj file that was added by accident 2023-02-08 00:23:41 -05:00
John Colvin 55d021ccb1 fix build (publish): Copy libspark.dll to publish dir
Bugs (fixed):
  * Spark.exe generated by the installer crashes immediately on launch because
    it cannot find the libspark.dll.

  Cause: Sure enough, libspark.dll isn't in the install folder
  (AppData\Roaming\bts\Spark)

* Build libspark explicitly
* Fix libspark.dll copy src path
2023-02-07 16:41:11 -05:00
Taha Afzal 60cde0712f Streamlining MarketDataGateway further - all sources are started independently of each other now, with their own GeneralMarketDataListener 2023-02-07 11:59:11 -05:00
arhamGIT 83127523b9 Merge branch 'spark_crypto.websocket-api' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api 2023-02-07 10:51:40 -05:00
arhamGIT 86c824e28d changed made to make js client work 2023-02-07 10:51:29 -05:00
arhamGIT 0349ff95bf book subscription working 2023-02-07 10:51:09 -05:00
Taha Afzal c20f017069 Simplified MarketDataGateway to deal with multiple market data producers as start-and-forget 2023-02-06 21:27:41 -05:00
John Colvin f62c867a20 feat (internal): Add trades md client 2023-02-06 19:42:43 -05:00
John Colvin b403cacb93 refactor: Simplify TradesSource SecurityCriteria filter 2023-02-06 19:42:43 -05:00
John Colvin 4499a3751f refactor: Move TradesSource to spark_api
So it can be used in the new websocket api
2023-02-06 19:42:43 -05:00
John Colvin 6d887cb72f refactor: Get rid of redundant Product struct 2023-02-06 19:42:43 -05:00
John Colvin 10e13dd51d refactor: Rename 'market_data' -> 'books' 2023-02-06 18:18:53 -05:00
Taha Afzal 5122038d21 Fixing windows side build 2023-02-06 15:21:51 -05:00
Taha Afzal 3039df56a0 Hooking up SimExecutionGateway to GeneralMarketDataListener 2023-02-06 14:04:57 -05:00
arhamGIT 85edf68ff0 secuirties working 2023-02-06 09:43:47 -05:00
arhamGIT 259ac99cdd books working 2023-02-06 09:25:12 -05:00
arhamGIT 39c3a34158 Merge branch 'spark_crypto.websocket-api' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api 2023-02-06 09:21:04 -05:00
arhamGIT dde8223052 books working 2023-02-06 09:05:32 -05:00
Taha Afzal 4dc675eb9c Getting rid of Jetfix's platform, using Security.proto's exchange 2023-02-05 20:24:29 -05:00
John Colvin 2548f27527 feat (internal): Add manual fills to orders client 2023-02-04 10:36:31 -05:00
John Colvin ff03f092f5 chore: Remove useless white space 2023-02-04 10:36:31 -05:00
John Colvin 53ef67869b refactor: Support null filters in orders client 2023-02-04 00:35:43 -05:00
John Colvin d48f34d109 feat (internal): Add fills to OrdersClient 2023-02-04 00:35:42 -05:00
John Colvin a2d9c39325 feat (internal): Add securities to md client 2023-02-04 00:32:29 -05:00
John Colvin 0c4f684036 improvement: Include qty display w/ BookTuple
This is needed to properly format json for websocket api
2023-02-04 00:09:24 -05:00
John Colvin e587c8dbd7 refactor: Rename IncrementalMarketDataClient w/out Incremental 2023-02-04 00:09:24 -05:00
John Colvin 069ab45164 improvement: Provide order updates w/ corresponding root order 2023-02-04 00:09:24 -05:00
John Colvin 7b7de6f8fc refactor: Move long 'RootDependent' lambda into own class 2023-02-04 00:09:23 -05:00
John Colvin 9ed3b2aecb refactor: Return IConnectableObservable in TableUpdate.Cache
We were hiding the fact that an IConnectableObservable was being used
internally. Even worse, we were discarding the IDisposable returned from
its 'Connect' fn.
2023-02-04 00:09:23 -05:00
John Colvin ecf3f922df refactor: Replace OrderSecurity refs w/ OrderRecordTuple
The latter type was introduced to support the websocket server. Unlike
the old 'OrderSecurity' types, it has no wpf deps, and can thus be built
on Linux
2023-02-04 00:04:43 -05:00
John Colvin 1aa283fc8c chore: Make AlgoID type public
It's referenced by outside projects, namely Spark. The build would have
been broken were it not for the 'InternalsVisibleTo' attribute.

TODO: Remove all 'InternalsVisibleTo' attributes (they smell hacky)
2023-02-04 00:04:43 -05:00
John Colvin bfbf640986 refactor: Move AccountSecurityKey to spark_api 2023-02-04 00:04:43 -05:00
John Colvin b6cd470ca6 refactor: Move AlgoDefinitionMetadata to spark_api
Part of larger effort to move deps from Spark to linux compatible projs
2023-02-04 00:04:43 -05:00
John Colvin d826cff9d7 chore: Remove unused code 2023-02-04 00:04:42 -05:00
John Colvin ff65a5ca5b refactor: Get rid of old MarketDataClient in sdk examples 2023-02-04 00:04:42 -05:00
arhamGIT 9e012a2b3a Merge branch 'spark_crypto.websocket-api' of bitbucket.org:bluetradesys/spark into spark_crypto.websocket-api 2023-02-02 11:29:04 -05:00
arhamGIT a6f1c51539 changes suggested by john for sub hdlr 2023-02-02 11:27:13 -05:00
John Colvin 655f27543b refactor: Include security w/ book data 2023-02-01 15:16:08 -05:00
John Colvin 762baca586 improvement: Add Errors enum mapped to exit code 2023-02-01 15:16:08 -05:00
John Colvin ec769b49f6 feat (internal): Add expirations to SecurityCriteria 2023-02-01 15:16:08 -05:00
John Colvin 5153e8725c refactor: Replace terse null/empty checks w/ is_null_or_empty 2023-02-01 15:16:08 -05:00
John Colvin f79f2cc5b9 chore: Add NotNullWhen(false) attr to 'is_null_or_empty' 2023-02-01 15:16:08 -05:00
John Colvin cdf4f341d4 fix: Consider SecurityCriteria 'defined' if callputs non-empty 2023-02-01 15:15:04 -05:00
John Colvin f649c26304 chore: Remove superfluous fn 2023-02-01 15:14:23 -05:00
John Colvin 3a8d759a26 refactor: Move OrderFactory to own file, merge w DynamicOrderHelper 2023-02-01 15:14:23 -05:00
John Colvin 29ca6e98fb refactor: Replace ShowOrderTicket tag's anon tuple w/ proper type 2023-02-01 15:14:22 -05:00
John Colvin 328dd9b2d3 feat (internal): Add OrdersClient 2023-02-01 15:14:22 -05:00
John Colvin a1e58e5498 feat (internal): Add AdminClient 2023-02-01 15:14:22 -05:00
John Colvin ef43aebc5d refactor: Remove misplaced admin-related fns from OrderFactory 2023-02-01 15:14:22 -05:00
John Colvin 9a3304201e refactor: Consolidate sync_with/never_duplicate fns 2023-02-01 15:14:22 -05:00
John Colvin cd88710385 refactor: Move order utils from spark to spark_api
This is part of a larger effort to decouple business logic from windows
and the ui. Some utils are immediately needed for the websocket api.
2023-02-01 10:07:43 -05:00
John Colvin 2b3e4a4579 refactor: Move DisplayNameHelper to spark_core 2023-02-01 10:07:43 -05:00
John Colvin 05731cb9a2 refactor: Add OrderPriceComparer spark_api proj 2023-02-01 10:07:42 -05:00
arhamGIT 01eeadaf42 added changed suggested by john 2023-02-01 03:29:22 -05:00
arhamGIT b4721882ec log.notnull instead of customs, removed helpers 2023-02-01 00:15:11 -05:00
arhamGIT 3e894d0e27 used LoggerContext instead of custom task 2023-02-01 00:08:07 -05:00
arhamGIT 4e42125398 changed Programs.cs to use task.wait 2023-01-31 23:58:11 -05:00
arhamGIT 664cc37a03 fixed small bug 2023-01-31 23:46:51 -05:00
arhamGIT f4a0da3518 code for book subcription building 2023-01-30 09:11:54 -05:00
Taha Afzal cc8c181728 Establishign the connection bw listener and sim execution 2023-01-27 17:13:06 -05:00
John Colvin 5339d4ff93 refactor: Impl 'market_data' fn w/ SecurityCriteria filter 2023-01-27 14:36:38 -05:00
John Colvin a31368f08d refactor: Make 'subscribe_md' fn criteria param nullable
It was already checking for null, just needed to add the '?' to convey
this to callers. Also improve the method by checking if SecurityCriteria
'is_defined' before applying the filter.
2023-01-27 14:36:38 -05:00
John Colvin 136938ba1e refactor: Add NotNullWhen attr to 'is_defined' ext
So static analysis tools recognize that the 'criteria' param must be
non-null when 'is_defined' returns true
2023-01-27 14:36:38 -05:00
John Colvin 09316b630d refactor: Make SecurityCriteria/Clause public 2023-01-27 14:36:38 -05:00
John Colvin 99a661089f refactor: Move Book into own file 2023-01-27 13:48:19 -05:00
arhamGIT f26cb80e5f changes for marketdataclient 2023-01-27 13:47:15 -05:00
Taha Afzal dde8524ecb Renaming some general classes and moving them out of cc 2023-01-26 23:22:36 -05:00
Taha Afzal cda3d18838 Simulted Exchange base classes added 2023-01-26 20:02:10 -05:00
arhamGIT fae0325e87 added dummy function 2023-01-26 14:21:14 -05:00
Taha Afzal 118ca7248d Merge branch 'spark_crypto.ccapi' of bitbucket.org:bluetradesys/spark into spark_crypto.ccapi 2023-01-25 17:01:51 -05:00
Taha Afzal afa194ac54 Fixing the live vs replay priority (In short, if an exchange is configured for both live and replay, live gets precedence. Also, replay market data is not recorded 2023-01-25 17:01:32 -05:00
John Colvin 3538712692 fix (mview): Raise prop changed for qty '_text' props
Bugs (fixed):
  * Quantities for Deribit futures are all 0

    Cause: The row wasn't refreshing qty '_text' props when the quantities
    changed
2023-01-24 23:24:37 -05:00
Taha Afzal 604c34384c Adding Deribit to the default MarketDataConfigs 2023-01-24 22:01:33 -05:00
Taha Afzal c18f1baafa Merge branch 'spark_crypto.ccapi' of bitbucket.org:bluetradesys/spark into spark_crypto.ccapi 2023-01-24 21:08:56 -05:00
Taha Afzal 8e04920ab9 Starting Deribit from MarketDataGateway 2023-01-24 21:08:24 -05:00
arhamGIT aa3147a4a6 Merge branch 'spark_crypto.dev' of bitbucket.org:bluetradesys/spark into spark_crypto.dev 2023-01-24 13:34:19 -05:00
arhamGIT f7ab968e1b added flow comments 2023-01-24 10:32:44 -05:00
arhamGIT 5ce3d9d1a9 updated datasync 2023-01-24 10:32:43 -05:00
arhamGIT e2a9c91d3f added comments 2023-01-24 10:32:43 -05:00
arhamGIT 78a8652e7a separated logic into three classes needs comments 2023-01-24 10:32:43 -05:00
arhamGIT e9c536df96 sockethandler done, need to give cons back to gtwy 2023-01-24 10:32:43 -05:00
arhamGIT 94429a1fbc merged trydisconnecting with other function 2023-01-24 10:32:43 -05:00
arhamGIT f2728dcf78 thread safe socket added 2023-01-24 10:32:43 -05:00
John Colvin cbfd18c371 ui (orderbook): Use qty display cfg in right panel 2023-01-24 00:51:54 -05:00
John Colvin 60a31eb102 chore: Remove unnecessary BTS_EXPORTs 2023-01-24 00:51:54 -05:00
John Colvin 7c1e95d35d ui (mview): Only show merged qty by default
Hide direct/implied qty cols
2023-01-24 00:51:54 -05:00
John Colvin 90a046d539 feat (ui): Use fractional qtys in md
Changing quantities from ints to floats introduces new rounding/display issues
(unlike with ints, we can't just call 'ToString()' and expect consistent
formatting). Formatting settings are needed, such as num-decimal-places and
display-multiplier, and they must be configurable per SecurityCriteria.

Fortunately, such configuration already exists in the form of SecurityMetadata
config (we tackled the same issue for order-entry). In order to integrate this
(newer) config with market data, references to the (older)
SymbolUIConfiguration (used once upon a time for DJ work), had to be replaced.
2023-01-24 00:51:53 -05:00
John Colvin 935a6f846c fix build (client): Disable cpp that isn't needed on win 2023-01-24 00:51:44 -05:00
John Colvin b02f814c65 fix (ui): Remove context menu items that do nothing
They were accidentally brought over from Edge. Their functionality
hasn't been implemented in Spark.
2023-01-23 01:34:55 -05:00
John Colvin 8c42aa93a2 chore: Remove unused code 2023-01-23 01:34:55 -05:00
John Colvin 357bc5ad44 fix (ui): Format perp futs 'Perp' suffix (not bogus exp) 2023-01-23 01:34:55 -05:00
John Colvin 07fb9e8eb7 ui (pnl): Use 'default_text' foreground in popup titles
Previously, the foreground for some popups was a hardcoded dark gray,
which became hard-to-read following the Dark Theme changes.
2023-01-23 01:34:55 -05:00
Taha Afzal d641eba252 Removing some unused headers from includes 2023-01-22 18:38:31 -05:00
John Colvin 9f9fc4c8ab fix (analytics-exps): Wait for sym list before loading selection
Bugs (fixed):
   * The selected symbols aren't restored with the workspace

   Cause: The selected symbols were getting loaded once, in the ctr, before the
   list of symbols had been properly initialized. The view automatically
   deselects items that aren't in the ItemsSource.
2023-01-22 12:23:03 -05:00
John Colvin 2aef052398 ui (pnl): Use gray font color when pnl is zero 2023-01-22 12:23:03 -05:00
John Colvin 1c2027506a refactor: Clean up NullableColor/FontWeightProto 2023-01-22 12:23:03 -05:00
John Colvin c3274b2008 refactor: Rename argb_color -> to_uint
This is a more appropriate name
2023-01-22 00:11:28 -05:00
John Colvin 99aef9e86e refactor: Get rid of redundant prop 'NullableColorProto.argb'
It was a relic of the past. Although different fns are called in the props'
getters ('rgb_color' vs 'argb_color'), both ultimately return the same value.
2023-01-22 00:09:38 -05:00
Taha Afzal 77697f4312 Fixing windows C++ build 2023-01-21 22:16:35 -05:00
Taha Afzal 247d8b7ee8 Merging 2023-01-21 20:57:59 -05:00
Taha Afzal 06bed8747f Adding Replay to MarketDataGateway 2023-01-21 20:38:37 -05:00
John Colvin 8e9233022e fix (mini-ob): Return root element in CancelColumn.view_factory
Bugs (fixed):
  * Mini Orderbook crashes immediately when opened

  Cause: The (cell) view_factory fn wasn't returning the cell's root
  element, and was instead returning the root's child element.
  As a result, when the row attempted to add this element to its visual
  tree, the following exception was thrown:

    System.ArgumentException: Specified Visual is already a child of
    another Visual or the root of a CompositionTarget.
2023-01-21 13:41:04 -05:00
John Colvin 954dc582dc fix build: Make non-class fns in cpp files static
The build was broken bc a fn w/ signature 'eq(double, double)' was
defined twice, in TaskingEyeAlgo.cpp and CCAPISingleOrderManager.cpp.
2023-01-20 15:08:21 -05:00
John Colvin df510f0e3b Merge origin/spark_crypto.ccapi.fractional_qty_md 2023-01-20 15:08:19 -05:00
Taha Afzal ef9b3b0544 Adding config protobuf for MD Replay 2023-01-20 11:35:58 -05:00
Taha Afzal b8b3a57e8e Putting recording behind config 2023-01-19 23:09:28 -05:00
Taha Afzal d18020a45c Merging spark_crypto.md_recording 2023-01-19 15:31:36 -05:00
Taha Afzal e652c1cd24 Fixing the build (as per John) 2023-01-18 13:11:25 -05:00
Taha Afzal 8f5d6ccd51 Organized the common md recording functions 2023-01-17 23:36:04 -05:00
Taha Afzal cbe4a488b9 Adding error handling for file based replay 2023-01-17 22:09:17 -05:00
Taha Afzal 8ce3ef69d0 Odds and Ends with replay 2023-01-17 17:09:02 -05:00
Taha Afzal ab9fab13d9 Merging from spark_crypto.cme 2023-01-17 11:25:23 -05:00
Taha Afzal 309b0e64b2 Adding better logs 2023-01-16 21:46:27 -05:00
arhamGIT a6324a9aa2 added flow comments 2023-01-16 13:19:39 -05:00
arhamGIT 64417a6867 updated datasync 2023-01-16 03:21:42 -05:00
arhamGIT 8e16dcde0d added comments 2023-01-16 02:25:18 -05:00
Taha Afzal 2d8f6df0e2 Adding SimExecutionGateway, its not implemented yet 2023-01-15 19:09:21 -05:00
Taha Afzal 10199fb7ad Adding spread support in replay 2023-01-13 16:20:33 -05:00
arhamGIT 6f6ac2866c separated logic into three classes needs comments 2023-01-13 07:21:10 -05:00
arhamGIT 46837facbf sockethandler done, need to give cons back to gtwy 2023-01-13 05:55:12 -05:00
John Colvin 4916211301 refactor: Add BTS_FATAL macros
Essentially just shorthand for 'bts_assert(false)'
2023-01-12 12:50:29 -05:00
John Colvin 1d8c4a0954 chore: Add various MarketDataConfig.conf profiles 2023-01-12 12:50:28 -05:00
John Colvin 64601914b2 feat: Add Binance US market data 2023-01-12 12:50:28 -05:00
John Colvin b3ca5f133e build: Add config profiles to override generated defaults 2023-01-12 12:50:28 -05:00
John Colvin 9c3397d367 build (web): Upgrade node packages
As of now (2022-01-03), only 1 package isn't up-to-date: 'protobufjs'.
It remains locked at version 6.11.3. Anything newer breaks the web build
with mysterious webpack errors that suggest various imports aren't
properly resolved.
2023-01-12 12:50:28 -05:00
John Colvin b3dfce9f91 build (web): Automatically generate protos in venv
Finally, the server can be built outside of the venv (all dependent
build steps activate it automatically)
2023-01-12 12:50:28 -05:00
John Colvin 590d0028c2 chore: Add '!=' operator for Book
The '==' operator had already been defined. Presumably, the '!='
operator was omitted by mistake.
2023-01-12 12:50:28 -05:00
John Colvin 67cf817aa9 chore: Impl to/from_json for domain/md types
So objects of these types can be readily logged in a format that is
comprehensive, familiar, and consistent
2023-01-12 12:50:28 -05:00
John Colvin 35811512a4 chore: Remove FTX from default md conf
FTX is no more
2023-01-12 12:50:28 -05:00
John Colvin c13c85ed44 refactor: Rename 'num_book_levels' -> 'num_depth_levels'
This seems to be a more common nomenclature
2023-01-12 12:50:28 -05:00
John Colvin 5c85dabad8 fix (ccapi logging): Store filename strings in buffer
So they don't point to bogus memory when the log is persisted (async)
2023-01-12 12:50:28 -05:00
John Colvin c134b0f5ca refactor: Move 'AllSameType' to its own header 2023-01-12 12:50:28 -05:00
John Colvin d92ad7e2b6 build: Make ccapi log level configurable via cmake cache var
Default to 'Debug' for debug builds, and 'Warn' for release builds
2023-01-12 12:50:28 -05:00
John Colvin 4547d8cec1 refactor: Add runtime cfg for exch urls
CCApi otherwise harcodes them as pre-processor definitions (compile time).
We can use this runtime cfg to switch between test/prod urls without rebuilding
2023-01-12 12:50:28 -05:00
John Colvin 402a1f50f2 chore: Clean up Symbols.conf a bit 2023-01-12 12:50:28 -05:00
John Colvin bada16ade7 chore: Add documentation for TimeStamp 2023-01-12 12:50:28 -05:00
John Colvin 9794465d88 fix build (gcc): Mark a few constexpr fns inline instead
The gcc compiler correctly detected the impls weren't constant expressions
2023-01-12 12:50:28 -05:00
John Colvin 1f163615c5 style: Run formatter on CMakeLists 2023-01-12 12:50:28 -05:00
John Colvin 4304d7f786 diag: Add output op & fmt impl for SecurityMarketDataStatistics 2023-01-12 12:50:28 -05:00
John Colvin 38a5d95df9 refactor: Change md config to support multiple venues at once 2023-01-12 12:50:28 -05:00
John Colvin 4897195629 feat: Add Binance USDS Futures market data 2023-01-12 12:50:28 -05:00
John Colvin 1416f05fbd chore: Remove unused protos 2023-01-12 12:50:28 -05:00
John Colvin ac1f64c3f5 fix build (sparkd): Add '-g' to cxx debug flags
Technically, the build wasn't broken, just the legacy script 'build_sparkd.py'.
The latest build procedure, which uses CMakePresets, doesn't have this problem.
2023-01-12 12:50:28 -05:00
John Colvin 8fa82840be feat: Add Binance market data
Restructure build configurations so 'dev' builds target venue test urls,
while 'prod' builds target production urls (technically, there is only
one prod build at the moment; it's compiled w/ gcc/release). This is
necessary because the urls ccapi uses are defined at compile time (all
seem to be pre-processor directives defined in ccapi_macro.h).
2023-01-12 12:50:28 -05:00
Taha Afzal af92b8922f MD Recording and Replay is almost done, some cleanup needed - mainly organizing config, better logs and some code comments 2023-01-12 09:59:01 -05:00
arhamGIT f3d1569cb3 merged trydisconnecting with other function 2023-01-12 09:45:59 -05:00
arhamGIT da41a23c0e thread safe socket added 2023-01-11 06:32:07 -05:00
Taha Afzal e79aebbc8a MDRecorder cleanup: 2023-01-09 23:20:46 -05:00
Taha Afzal fcd6038d5d Added implied market data to MDRecorder 2023-01-09 13:36:28 -05:00
Taha Afzal d1fe0a03b5 MDRecorder almost done, need record implied and RFQ requests, as well as exit after an alloted time of recording 2023-01-09 09:38:03 -05:00
Taha Afzal cfdca08cfe CME Template 8 2023-01-06 11:52:30 -05:00
John Colvin d400bf6263 refactor: Rename spartan 'FMT' macro 'TO_STRING'
Avoids conflict with new 'FMT' macro, which is an alias for 'fmt::format'
2023-01-04 13:35:38 -05:00
John Colvin fa438db001 style: Add 'ReflowComments: false' to clang-format
So clang-format doesn't make pretty doxygen comments ugly (it doesn't
seem to know how to format them properly).
2023-01-04 13:35:38 -05:00
John Colvin 31dd34522f chore: Add sec_descs to SecurityCriteria (cpp)
Corresponds to the 'names' field in SecurityCriteria proto
2023-01-04 13:35:38 -05:00
John Colvin f5221910c8 fix: Support Spots in security sort impl 2023-01-04 13:35:38 -05:00
John Colvin 6e7e1980f5 fix (temp): Skip duplicate sec-exp keys in old edge code
It wasn't designed to support multiple exchanges, so Futures with the same
sym/exp from different exchanges yield duplicate sec-exp keys.
2023-01-04 13:35:38 -05:00
John Colvin 11e884e166 fix build (win): Build files in 'core' dir 2023-01-04 13:35:38 -05:00
John Colvin 88943f0857 refactor: Pass ostream to LiveLadderPrinter (don't hardcode cout) 2023-01-04 13:35:38 -05:00
John Colvin a5459a3aff improve: Optimize BookSide::is_sorted 2023-01-04 13:35:38 -05:00
John Colvin e8fa4f23c6 refactor: Move ProtoReader/Printer to 'bts::io' ns 2023-01-04 13:35:38 -05:00
John Colvin df82c0790b fix: Remove leftover test-code flag
It was preventing securities from being propagated to shared memory
2023-01-04 13:35:38 -05:00
John Colvin 81f1d91f5b style: Run clang-format on lib/md dir 2023-01-04 13:35:38 -05:00
John Colvin abf0d45784 improvement: Refactor mdgw/ftx to use SecurityCriteria
So we can subscribe to depth for "FTX Options" or "FTX BTC Futures",
rather than having to list each security explicitly.

This commit also unhooks binance from MarketDataGateway. A new paradigm
is emerging with the FTX impl, and it'll be easier to redo Binance than
try to make the existing impl fit the new mold.

Unfortunately, ccapi doesn't provide all the security metadata we need, such as
the security type and expiration date/time, so we get the list of FTX
securities directly from the exchange.
2023-01-04 13:35:38 -05:00
John Colvin 556e2ab99e refactor (chore): Clean up domain::Security a bit
* Rename 'min_quantity_increment_ammount' -> 'min_quantity_increment' to fix typo
* Remove old 'min_quantity_increment' member (it wasn't referenced anywhere)
* Initialize SecurityCommon w/ reasonable defaults (skipping initialization seems
like a premature performance optimization)
* Add a few members to verbose 'to_string' result
2023-01-04 13:35:38 -05:00
John Colvin 4b60fb5141 chore: Add nifty EnumMacros to replace boilerplate code 2023-01-04 13:35:38 -05:00
John Colvin 5eb9c57ba1 refactor: Use core::TimeStamp instead of chrono in TradeRecord 2023-01-04 13:35:38 -05:00
John Colvin e08b80afee chore: Make AggressorSide implicit convert from 'Value' 2023-01-04 13:35:38 -05:00
John Colvin 9b8e5896a2 chore: Remove unnecessary include 2023-01-04 13:35:38 -05:00
John Colvin 55e8c60a0b chore: Move ContainsKey macro to lib/collections 2023-01-04 13:35:38 -05:00
John Colvin a30b026c9d chore: Tone down IDGenerator logging to Diag 2023-01-04 13:35:38 -05:00
John Colvin cb79cbeb45 chore: Move SecurityCriteria classes into libspark 2023-01-04 13:35:38 -05:00
John Colvin 0e101aaf8b improvement: Show sid in LiveLadderPrinter book output 2023-01-04 13:35:38 -05:00
John Colvin e8244595f3 chore: Add to_string fn to Security
For diagnostic purposes (esp while we integrate more exchanges)
2023-01-04 13:35:38 -05:00
John Colvin 37512eb8d6 chore: Add some basic functionality to core::TimeStamp 2023-01-04 13:35:38 -05:00
John Colvin 567db063f3 fix: Create string in FMT_IMPL macro so it's compatible w/ LOG
Otherwise variables which aren't copied by default become corrupt when they go
out of scope (which happens bc our logging system is async).
2023-01-04 13:35:38 -05:00
John Colvin cc1484a81e chore: Move OSTREAM_FMT_IMPL.h into lib/core 2023-01-04 13:35:38 -05:00
John Colvin 0dc278eed5 chore: Support timezones when parsing iso dates
This is needed because FTX (and perhaps other exchanges) format
expirations with timezones
2023-01-04 13:35:38 -05:00
John Colvin 43ba30365a fix: Update OSTREAM_FMT_IMPL macro
This macro defines 2 template specialization fns, 'parse' and 'format'.

* Change 'format' to be a const method
* Declare return type w/ 'decltype' (per latest official example from fmtlib)
2023-01-04 13:35:38 -05:00
John Colvin 02ac95404d chore: Remove unused files 2023-01-04 13:35:38 -05:00
John Colvin 8388bdf1ec chore: Add missing huobi & binance venues to 'Venue' proto 2023-01-04 13:35:38 -05:00
John Colvin 019c3dd8db chore: Replace magic strings w/ CCAPI macros
These come from ccapi, so the code should never break due to an update
(not necessarily the case with the magic strings).
2023-01-04 13:35:38 -05:00
John Colvin 481380f883 chore: Assign asset & group when parsing ccapi securities 2023-01-04 13:35:38 -05:00
John Colvin 7c66260ff1 chore: Rename 'security_type' -> 'type'
For convenience (it's shorter)
2023-01-04 13:35:38 -05:00
John Colvin ad465b593f chore: Add fns to access SecurityCommon fields from Security
Bc I'm lazy and don't want to write 'security_common' everytime I need to access
these fields
2023-01-04 13:35:38 -05:00
John Colvin 00d702f998 chore: Remove accidental include 2023-01-04 13:35:38 -05:00
Taha Afzal 872f55d6c3 Reducing the logs and couts that were put while interfacing with CC 2023-01-04 13:35:38 -05:00
Taha Afzal 84f4c38336 Enabling spot market dtaa in the UI 2023-01-04 13:35:38 -05:00
Taha Afzal b9b907490a Enabling spot market data 2023-01-04 13:35:38 -05:00
Taha Afzal 8c6835a919 Merging 2023-01-04 13:35:38 -05:00
Taha Afzal 3a6bda4e08 Removing temporary security creation from CCMarketDataListener 2023-01-04 13:35:38 -05:00
Taha Afzal 60f76344c2 UI changes in SecurityExtensions to accomodate FTX 2023-01-04 13:35:38 -05:00
Taha Afzal 1fff7d5bcd Removing #include of a deleted generated header 2023-01-04 13:35:38 -05:00
Taha Afzal d77d3ab6c7 Merging CCListener work from a different branch 2023-01-04 13:35:35 -05:00
arhamGIT 4c91538f22 base websockets working 2023-01-04 04:34:44 -05:00
Taha Afzal 2eca4f7f14 Fixing the build, unused variable 2023-01-03 14:53:03 -05:00
John Colvin 053fa461a2 chore: Remove unnecessary includes 2023-01-03 14:53:03 -05:00
John Colvin aa997466f0 chore: Remove unused files CCApiRequestor.h/cpp 2023-01-03 14:53:03 -05:00
John Colvin fdf4fce5fa refactor: Return error if md cfg invalid rather than assert/crash 2023-01-03 14:53:00 -05:00
Taha Afzal 5746460e8d QueryServer while handling mic's use switch for exchange instead of ifs 2023-01-02 18:44:59 -05:00
John Colvin 569ac8e3e0 fix: Fix typo in 'MarketDataRegistrationError' type name
The 'Registration' part was misspelled 'Regstration'
2023-01-02 18:44:59 -05:00
Taha Afzal d9efbb879d IDGenerator is a thread-safe singleton now 2023-01-02 18:44:59 -05:00
John Colvin 92ff4198ef refactor: Hook up ccapi 'on_securities' callback
Clean up ccapi md code while we're at it
2023-01-02 18:44:59 -05:00
John Colvin 48bd3ab49a chore: Remove Binance-specific md impl from MarketDataGateway
It was creating needless clutter, as it was written before we knew about
ccapi. The new plan is to use a simple adaptor to interface with ccapi
for every exchange md.

Note: There are a handful of files related to the historic Binance impl
in the folder /lib/md/binance. I'm keeping them around for now, since
they are generally independent/isolated, and aren't causing clutter or
compromsing other code. Some of the utils there may come in handy down
the road.
2023-01-02 18:44:59 -05:00
John Colvin 9c7fc000e5 refactor: Replace FTX ccapi impl w/ exchange agnostic one 2023-01-02 18:44:59 -05:00
John Colvin d2454b6b85 chore: Include <string> in MarketDataRegistrationError
Apparently <string> was included in all source files that referenced
MarketDataRegistrationError by coicidence (else the build would have been broken)
2023-01-02 18:44:59 -05:00
John Colvin b4cda81535 build: Add -g to CMAKE_CXX_FLAGS_DEBUG
This flag tells compilers (both clang and gcc) to produce debug info
2023-01-02 18:44:59 -05:00
John Colvin 2d0fae0cbe chore: Sort includes 2023-01-02 18:44:59 -05:00
Taha Afzal 5515404062 CCMarketDataListener now listens to CC and writes data to shared memory 2023-01-02 18:44:57 -05:00
John Colvin 24c4dc1861 fix build (g++-12 rel): Add '-Wnomaybe-uninitialized' flag
For some reason, this warning isn't suppressed in ccapi_date.h, which is
included as a system header (like all headers in externals). According to GCC's
documentation, compiler warnings shouldn't be emitted from system headers.

Disabling the warning for now so we can focus on bigger fish.
2023-01-02 18:42:39 -05:00
John Colvin 3b1a2357cc fix build (client): Change 'WIN32' macros to '_WIN32'
Not sure exactly how this broke, but the WIN32 macro is no longer defined.
2023-01-02 18:42:39 -05:00
John Colvin 35371fe971 refactor: Remove redundant optional.h
It was from a time when Windows std didn't provide the 'optional' header
2023-01-02 18:42:39 -05:00
John Colvin 365394f28b build: Fix build_spark.py (broken since CMakePresets introduced)
Pass additional cmake opts through cli. Specifically, those that were
moved from CMakeLists.txt to CMakePrests.json
2023-01-02 18:42:39 -05:00
John Colvin 88c70a3ea0 build (refactor): Add cmake_utils.py in py/core
So it can be referenced by both client/server build scripts
2023-01-02 18:42:39 -05:00
John Colvin b0eb1175c1 Update docker/linux for ubuntu 22.10 image 2023-01-02 18:42:39 -05:00
John Colvin e90d627125 build (web): Update npm packages 2023-01-02 18:42:39 -05:00
John Colvin c1190d4ef9 build (refactor): Remove unused cmake var SPARK_PYTHON 2023-01-02 18:42:39 -05:00
John Colvin 67487415ad build (refactor): Change some cmake cache vars to options 2023-01-02 18:42:39 -05:00
John Colvin dcf80d7067 build: Fix build_sparkd.py (broken since CMakePresets introduced)
Pass additional cmake opts through cli. Specifically, those that were
moved from CMakeLists.txt to CMakePrests.json
2023-01-02 18:42:39 -05:00
John Colvin 99a778811a fix build: Update externals
Disables a few warnings-as-errors in btree source files
2023-01-02 18:42:39 -05:00
John Colvin eb76f0a6c5 fix build (gcc-12, clang>=11): Update externals
Disables a few warnings-as-errors in catch2 source files
2023-01-02 18:42:39 -05:00
John Colvin b8de813859 build: Replace setup_builds w/ CMakePresets.json
Clean up CMakeLists a bit in the process:
   * Define more cmake vars in CMakePresets
   * Split linux/windows presets into separate files
2023-01-02 18:42:39 -05:00
John Colvin 6b480afd43 build (sparkd): Automatically create py venv in build script 2023-01-02 18:42:39 -05:00
John Colvin 40d21542ae build (sparkd): Pipe 'eval' cmd stdout/err back to shell
So we can actually see the build output
2023-01-02 18:42:39 -05:00
John Colvin a8af5d2523 fix build: Compile with gcc/g++ (version agnostic)
We don't really need a strict dependency on a compiler version, though
best practice is to use the latest gcc (12).
2023-01-02 18:42:39 -05:00
John Colvin bfd12aed63 tools (log): Fix 'pretty' script & rename 'show_last_run' 2023-01-02 18:42:39 -05:00
John Colvin 76936ea50d fix build (gcc): Disable warning stringop-overread
This warning (as error) was introduced with g++ 12
2023-01-02 18:42:39 -05:00
John Colvin 6947aea35e diag: Log emumba cfg parse error code 2023-01-02 18:42:39 -05:00
John Colvin 34be51c648 refactor: Include <limits> in sane_algorithm.h
Although the build was fine, many methods in this header file depend on 'limits'
so it is appropriate to include it. Presumably all references to such methods are
made from source files that include <limits> by coincidence.
2023-01-02 18:42:39 -05:00
John Colvin 56b68b9a24 fix build (gcc): Don't let switch case fall through
Even if the case is simply 'bts_assert(false)'
2023-01-02 18:42:38 -05:00
John Colvin 84e6f010d7 build: Benign changes to remove errors in gcc 12 2023-01-02 18:42:38 -05:00
John Colvin b360f953db build: Benign changes to remove errors in clang 15 2023-01-02 18:42:38 -05:00
Taha Afzal 320427c9c5 Merge branch 'spark_crypto.dev' of bitbucket.org:bluetradesys/spark into spark_crypto.dev 2022-12-25 16:17:12 -05:00
Taha Afzal 5e8543902e Sheet theos change colors for contracts that are in a task 2022-12-25 16:17:01 -05:00
Taha Afzal 51c89fb8cc Merge branch 'spark_crypto.prod' into spark_crypto.cme 2022-12-21 20:38:42 -05:00
Taha Afzal ded674d87c Enabling CME market data, and adding some new logs to track initialization of resources 2022-12-19 14:15:04 -05:00
3000 changed files with 378777 additions and 660173 deletions

No files matched your search

+1
View File
@@ -4,6 +4,7 @@ BinPackParameters: false
AlignAfterOpenBracket: AlwaysBreak
AlwaysBreakTemplateDeclarations: true
PenaltyReturnTypeOnItsOwnLine: 140
ReflowComments: false
---
Language: Proto
IndentWidth: 2
+19 -1
View File
@@ -7,6 +7,24 @@
"commands": [
"dotnet-format"
]
},
"fable": {
"version": "4.0.6",
"commands": [
"fable"
]
},
"fantomas": {
"version": "5.2.2",
"commands": [
"fantomas"
]
},
"fake-cli": {
"version": "6.0.0",
"commands": [
"fake"
]
}
}
}
}
+30 -16
View File
@@ -207,17 +207,23 @@ dotnet_naming_symbols.parameters.applicable_accessibilities = public,internal,pr
dotnet_naming_symbols.private_symbols.applicable_kinds = property,method,field,event,delegate
dotnet_naming_symbols.private_symbols.applicable_accessibilities = protected,private
# local symbols
dotnet_naming_symbols.local_symbols.applicable_kinds = local
# parameter symbols
dotnet_naming_symbols.parameter_symbols.applicable_kinds = parameter
# Naming styles
dotnet_naming_style.snake_case.required_prefix =
dotnet_naming_style.snake_case.required_suffix =
dotnet_naming_style.snake_case.word_separator = _
dotnet_naming_style.snake_case.capitalization = all_lower
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.private_snake_case.required_prefix = _
dotnet_naming_style.private_snake_case.required_suffix =
dotnet_naming_style.private_snake_case.word_separator = _
dotnet_naming_style.private_snake_case.capitalization = all_lower
dotnet_naming_style.camel_case.required_prefix =
dotnet_naming_style.camel_case.required_suffix =
dotnet_naming_style.camel_case.word_separator =
dotnet_naming_style.camel_case.capitalization = camel_case
dotnet_naming_style.user_types.required_prefix =
dotnet_naming_style.user_types.required_suffix =
@@ -229,6 +235,10 @@ dotnet_naming_style.interface.required_suffix =
dotnet_naming_style.interface.word_separator =
dotnet_naming_style.interface.capitalization = pascal_case
dotnet_naming_style.local.capitalization = camel_case
dotnet_naming_style.parameter.capitalization = camel_case
# rules
dotnet_naming_rule.user_types.symbols = user_types
dotnet_naming_rule.user_types.style = user_types
@@ -238,14 +248,18 @@ dotnet_naming_rule.interfaces.symbols = interface
dotnet_naming_rule.interfaces.style = interface_style
dotnet_naming_rule.interfaces.severity = suggestion
dotnet_naming_rule.public_members_snake_case.symbols = public_symbols
dotnet_naming_rule.public_members_snake_case.style = snake_case
dotnet_naming_rule.public_members_snake_case.severity = suggestion
dotnet_naming_rule.public_members.symbols = public_symbols
dotnet_naming_rule.public_members.style = pascal_case
dotnet_naming_rule.public_members.severity = suggestion
dotnet_naming_rule.private_members_snake_case.symbols = private_symbols
dotnet_naming_rule.private_members_snake_case.style = private_snake_case
dotnet_naming_rule.private_members_snake_case.severity = suggestion
dotnet_naming_rule.private_members.symbols = private_symbols
dotnet_naming_rule.private_members.style = camel_case
dotnet_naming_rule.private_members.severity = suggestion
dotnet_naming_rule.parameters.symbols = parameters
dotnet_naming_rule.parameters.style = snake_case
dotnet_naming_rule.variables_are_camel_case.severity = suggestion
dotnet_naming_rule.variables_are_camel_case.symbols = local_symbols
dotnet_naming_rule.variables_are_camel_case.style = local
dotnet_naming_rule.parameters.symbols = parameter_symbols
dotnet_naming_rule.parameters.style = parameter
dotnet_naming_rule.parameters.severity = suggestion
+9 -3
View File
@@ -47,7 +47,13 @@ trace_data/
/src/.clang-format
/src/server/sparkd/cmds/spartan/analysis/.ipynb_checkpoints
/src/server/sparkd/cmds/spartan/analysis/data
*.tmp/*
/.venv*/*
.tmp/
.venv*/
.cache/
src/web/api/tsconfig.*.g.json
/src/Spark.Admin.WebApp/tsconfig.*.g.json
/src/Spark.Admin.WebApp/src/bin/
**/CMakeDeps.cmake
**/CMakeDeps_win.cmake
**/.devcontainer
*.Generated.cs
*.lst
+4 -7
View File
@@ -1,9 +1,6 @@
[submodule "externals"]
path = externals
url = git@bitbucket.org:bluetradesys/externals.git
[submodule "docker/linux"]
path = docker/linux
url = git@bitbucket.org:bluetradesys/linux_docker.git
[submodule "docker/windows"]
path = docker/windows
url = git@bitbucket.org:bluetradesys/windows_docker.git
url = https://x-token-auth:ATCTT3xFfGN0h_ENnUSfEAIzbfVzkQPLG26cIli50MtcTwZ7VEc8lin5tJYqibjlBJ9PM9R642Ra5GjiL52TBfbO8KeUBT0UoMT7gLQHL2Y1TkW9yZr6NkvsoDkSl49DeD4Ijiu4_0u4qEm4oMVDDg2_fB059-uOWOo7ZL94tGZET8CSVpFIGvs=B0E03660@bitbucket.org/bluetradesys/externals.git
[submodule "vcpkg"]
path = vcpkg
url = https://github.com/microsoft/vcpkg.git
+49
View File
@@ -0,0 +1,49 @@
# This configuration file was automatically generated by Gitpod.
# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml)
# and commit this file to your remote git repository to share the goodness with others.
# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart
image: gitpod/workspace-dotnet-8
tasks:
- name: Install Deps
init: |
(
set -e
sudo install-packages rapidjson-dev
sudo install-packages libssh2-1-dev
sudo install-packages openssh-server
sudo install-packages liblttng-ust-dev
sudo install-packages libpcap0.8-dev
sudo install-packages ccache
sudo ln -s $(which ccache) /usr/local/bin/clang
sudo ln -s $(which ccache) /usr/local/bin/clang++
sudo ln -s $(which ccache) /usr/local/bin/clang-17
sudo ln -s $(which ccache) /usr/local/bin/clang++-17
sudo ln -s $(which ccache) /usr/local/bin/gcc
sudo ln -s $(which ccache) /usr/local/bin/g++
sudo ln -s $(which ccache) /usr/local/bin/gcc-12
sudo ln -s $(which ccache) /usr/local/bin/g++-12
if [ -e externals/src/emumba/install_emumba-deribit-connector.sh ]; then
externals/src/emumba/install_emumba-deribit-connector.sh
fi
)
- name: Setup Python venv
init: |
python -m pip install --upgrade pip
python -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txt
ports:
- name: sparkd config
port: 8000
onOpen: notify
- name: sparkd bus
port: 8001
gitConfig:
alias.st: "status"
status.short: "true"
core.pager: "less -FXRS"
+115 -72
View File
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.12)
project(spark)
set(CMAKE_CXX_STANDARD 20)
if(WIN32)
set(platform "windows")
@@ -13,101 +14,143 @@ set(
CACHE
STRING
"External dependencies root folder (should contain folders: lib, bin, include")
set(SPARK_PYTHON "${EXTERNALS_ROOT}/python")
set(SPARK_BIN "${EXTERNALS_ROOT}/bin")
set(SPARK_INCLUDE "${EXTERNALS_ROOT}/include")
set(SPARK_LIB "${EXTERNALS_ROOT}/lib/${CMAKE_BUILD_TYPE}")
set(SPARK_LIB "${EXTERNALS_ROOT}/lib/$<CONFIG>")
set(BUILD_API_SERVER OFF CACHE BOOL "Build the api server")
set(BUILD_DOCS OFF CACHE BOOL "Build documentation")
set(BUILD_SDK OFF CACHE BOOL "Build the sdk")
set(BUILD_WEB ON CACHE BOOL "Build the web server")
if (WIN32)
set(BUILD_SPARKD OFF CACHE BOOL "Build sparkd")
set(BUILD_ADMIN_WEB_APP OFF CACHE BOOL "Build the Admin WebApp")
else()
set(BUILD_SPARKD ON CACHE BOOL "Build sparkd")
set(BUILD_ADMIN_WEB_APP ON CACHE BOOL "Build the Admin WebApp")
endif()
include_directories(BEFORE SYSTEM ${SPARK_INCLUDE} ${EXTERNALS_ROOT}/include/zlib)
link_directories(${SPARK_LIB})
if(WIN32)
# flags
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} \
/MP \
/WX /wd4251 /wd4250 /wd4251 /wd4244 /wd4267 /wd4355 /wd4275 /wd4345 \
/bigobj \
/DCURL_STATICLIB \
/D_WINSOCK_DEPRECATED_NO_WARNINGS \
/D__TBB_NO_IMPLICIT_LINKAGE \
/DBOOST_ALL_NO_LIB \
/std:c++17 \
/D_SCL_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_DEBUG} /MT")
set(
CMAKE_SHARED_LINKER_FLAGS_RELEASE
"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} \
/DEBUG \
/OPT:REF \
/OPT:ICF \
/LTCG")
if(BUILD_API_SERVER)
add_compile_definitions(SPARK_ENABLE_API_SERVER)
endif()
if(WIN32)
add_compile_definitions(SHARED_MEMORY_PREFIX="spark")
add_compile_definitions(APP_DATA_DIR="\$\{APPDATA\}/bts/")
# subdirs
add_subdirectory(src/lib)
else()
# make sparkd look for libspark.so in its directory
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH ".")
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install/${CMAKE_BUILD_TYPE}/sparkd")
add_compile_definitions(SPARK_ENABLE_CCAPI)
add_compile_definitions(CCAPI_ENABLE_SERVICE_MARKET_DATA)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_FTX)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE)
add_compile_definitions(CCAPI_ENABLE_LOG_WARN)
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install")
set(SPARK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/$<CONFIG>")
# flags
set(
CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} \
-fPIC \
-Wall \
-pedantic \
-Wextra \
-Werror \
-Wno-missing-braces \
-Wno-ignored-qualifiers \
--std=c++17 -fdiagnostics-color")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -DNDEBUG -O3")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wno-undef")
if(BUILD_API_SERVER)
add_compile_definitions(APP_DATA_DIR="\$\{HOME\}/spark_api/")
add_compile_definitions(SHARED_MEMORY_PREFIX="spark_api")
elseif(BUILD_SPARKD)
add_compile_definitions(SHARED_MEMORY_PREFIX="sparkd")
add_compile_definitions(APP_DATA_DIR="\$\{HOME\}/sparkdata/")
# Note: All macros that begin w/ 'CCAPI' are ccapi's macros (defined and/or
# read by their code). We override some below.
add_compile_definitions(SPARK_ENABLE_CCAPI)
# This allows us to override hardcoded exchange-urls with ones read from
# config (i.e., resolved at runtime rather than compile-time)
add_compile_definitions(CCAPI_EXPOSE_INTERNAL)
# Enable ccapi services
add_compile_definitions(CCAPI_ENABLE_SERVICE_MARKET_DATA)
add_compile_definitions(CCAPI_ENABLE_SERVICE_EXECUTION_MANAGEMENT)
# Enable ccapi exchanges
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_COIN_FUTURES)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_US)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE_USDS_FUTURES)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_COINBASE)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_DERIBIT)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_OKX)
set(CCAPI_LOG_LEVEL
"Warn"
CACHE STRING "<Fatal|Error|Warn|Info|Debug|Trace> Log level for ccapi")
string(TOUPPER "${CCAPI_LOG_LEVEL}" _ccapi_log_level_upper)
add_compile_definitions("CCAPI_ENABLE_LOG_${_ccapi_log_level_upper}")
# ** Binance **
add_compile_definitions(CCAPI_BINANCE_URL_REST_BASE="https://api.binance.com")
add_compile_definitions(BINANCE_INSTRUMENTS_PATH="/api/v3/exchangeInfo")
add_compile_definitions(BINANCE_PRICE_STATS_PATH="/api/v3/ticker/24hr")
# ** Binance US **
add_compile_definitions(BINANCE_US_INSTRUMENTS_PATH="/api/v3/exchangeInfo")
add_compile_definitions(BINANCE_US_PRICE_STATS_PATH="/api/v3/ticker/24hr")
# ** Binance USDS Futures **
add_compile_definitions(CCAPI_BINANCE_USDS_FUTURES_URL_REST_BASE="https://dapi.binance.com")
add_compile_definitions(BINANCE_USDS_FUTURES_INSTRUMENTS_PATH="/dapi/v1/exchangeInfo")
add_compile_definitions(BINANCE_USDS_FUTURES_PRICE_STATS_PATH="/dapi/v1/ticker/24hr")
# ** Deribit **
add_compile_definitions(DERIBIT_INSTRUMENT_PATH="/api/v2/public/get_instrument")
add_compile_definitions(DERIBIT_INSTRUMENTS_PATH="/api/v2/public/get_instruments")
add_compile_definitions(DERIBIT_COMBOS_PATH="/api/v2/public/get_combos")
add_compile_definitions(DERIBIT_TICKER_PATH="/api/v2/public/ticker")
add_compile_definitions(DERIBIT_CURRENCIES_METHOD="public/get_currencies")
add_compile_definitions(DERIBIT_INSTRUMENT_METHOD="public/get_instrument")
add_compile_definitions(DERIBIT_INSTRUMENTS_METHOD="public/get_instruments")
add_compile_definitions(DERIBIT_COMBO_DETAILS_METHOD="public/get_combo_details")
add_compile_definitions(DERIBIT_COMBOS_METHOD="public/get_combos")
# ** Okx **
add_compile_definitions(OKX_INSTRUMENTS_PATH="/api/v5/public/instruments")
add_compile_definitions(OKX_UNDERLYING_PATH="/api/v5/public/underlying")
endif()
# subdirs
add_subdirectory(src/server/sparkd)
if (BUILD_SPARKD)
add_subdirectory(src/server/sparkd)
add_subdirectory(src/data_files)
endif()
add_subdirectory(src/lib)
if (BUILD_WEB)
add_subdirectory(src/web)
if (BUILD_ADMIN_WEB_APP)
add_subdirectory(src/Spark.Admin.WebApp)
endif()
if(BUILD_DOCS)
add_subdirectory(doc/user)
endif()
add_subdirectory(doc/user)
if(BUILD_SDK)
add_subdirectory(src/sdk)
endif()
add_subdirectory(src/data_files)
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/server
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/server/sparkd/sparkd ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/web ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/data_files ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/lib/libspark.so ${CMAKE_BINARY_DIR}/server
COMMAND
ln ARGS -sf
${EXTERNALS_ROOT}/lib/Release/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0
${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libACE-5.7.5.so ${CMAKE_BINARY_DIR}/server
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/server/plugins
COMMENT "Creating server runtime layout"
DEPENDS sparkd data_files_dir)
if(BUILD_SPARKD)
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/server
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/server/sparkd/sparkd ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/data_files ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/lib/libspark.so ${CMAKE_BINARY_DIR}/server
COMMAND
ln ARGS -sf
${EXTERNALS_ROOT}/lib/Release/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0
${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libACE-5.7.5.so ${CMAKE_BINARY_DIR}/server
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/server/plugins
COMMENT "Creating server runtime layout"
DEPENDS sparkd data_files_dir)
add_custom_target(server_layout ALL DEPENDS ${CMAKE_BINARY_DIR}/server)
add_custom_target(server_layout ALL DEPENDS ${CMAKE_BINARY_DIR}/server)
install(DIRECTORY "${CMAKE_BINARY_DIR}/server/plugins" DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/externals/linux/lib/${CMAKE_BUILD_TYPE}/libACE-5.7.5.so" DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/externals/linux/lib/${CMAKE_BUILD_TYPE}/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0" DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/externals/src/emumba/sparkd.lic" DESTINATION bin)
install(
DIRECTORY "${CMAKE_BINARY_DIR}/server/plugins"
DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
install(
FILES
"${SPARK_LIB}/libACE-5.7.5.so"
"${SPARK_LIB}/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0"
DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
endif()
endif()
+387
View File
@@ -0,0 +1,387 @@
{
"version": 4,
"cmakeMinimumRequired": {
"major": 3,
"minor": 23,
"patch": 0
},
"configurePresets": [
{
"name": "spark",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"generator": "Visual Studio 17 2022",
"binaryDir": "${sourceDir}/build",
"environment": {
"SPARK_CMAKE_CXX_FLAGS": "/MP /WX /wd4250 /wd4251 /wd4244 /wd4267 /wd4355 /wd4275 /wd4345 /bigobj /EHsc /DCURL_STATICLIB /D_WINSOCK_DEPRECATED_NO_WARNINGS /D__TBB_NO_IMPLICIT_LINKAGE /DBOOST_ALL_NO_LIB /std:c++20 /D_SCL_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600"
},
"cacheVariables": {
"CMAKE_CXX_FLAGS": "$env{SPARK_CMAKE_CXX_FLAGS}",
"CMAKE_CXX_FLAGS_DEBUG": "$env{SPARK_CMAKE_CXX_FLAGS} /MTd",
"CMAKE_CXX_FLAGS_RELEASE": "$env{SPARK_CMAKE_CXX_FLAGS} /MT",
"CMAKE_CXX_STANDARD": "20",
"CMAKE_SHARED_LINKER_FLAGS_DEBUG": "/DEBUG",
"CMAKE_SHARED_LINKER_FLAGS_RELEASE": "/OPT:REF /OPT:ICF /LTCG",
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
"EXTERNALS_ROOT": "${sourceDir}/externals/windows",
"CONFIG_DEFAULTS_PATH": "config/profiles/default/*.conf",
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net8.0",
"DOTNET_WINDOWS_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net8.0-windows"
}
},
{
"name": "sparkd",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"platform": "",
"CMAKE_BUILD_WITH_INSTALL_RPATH": {
"type": "BOOL",
"value": "ON"
},
"CMAKE_CXX_STANDARD": "20",
"CMAKE_INSTALL_RPATH": ".",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}/sparkd",
"CMAKE_EXE_LINKER_FLAGS": "-Wno-undef",
"EXTERNALS_ROOT": "${sourceDir}/externals/linux",
"BUILD_SDK": {
"type": "BOOL",
"value": "OFF"
},
"BUILD_ADMIN_WEB_APP": {
"type": "BOOL",
"value": "ON"
}
}
},
{
"name": "sparkd-debug",
"inherits": "sparkd",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": {
"type": "BOOL",
"value": "ON"
},
"CCAPI_LOG_LEVEL": "Info",
"CONFIG_DEFAULTS_PATH": "config/profiles/md_dev/*.conf;config/profiles/default/*.conf"
}
},
{
"name": "sparkd-release",
"inherits": "sparkd",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CCAPI_LOG_LEVEL": "Warn",
"CONFIG_DEFAULTS_PATH": "config/profiles/md_prod/*.conf;config/profiles/default/*.conf"
}
},
{
"name": "sparkd-debug-clang",
"inherits": "sparkd-debug",
"displayName": "Debug (clang)",
"description": "Debug build compiled w/ clang",
"binaryDir": "${sourceDir}/build/clang/debug",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -DDEBUG",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/clang/debug/sparkd"
}
},
{
"name": "sparkd-debug-gcc",
"inherits": "sparkd-debug",
"displayName": "Debug (gcc)",
"description": "Debug build compiled w/ gcc",
"binaryDir": "${sourceDir}/build/gcc/debug",
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc",
"CMAKE_CXX_COMPILER": "g++",
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -Wno-stringop-overread -DDEBUG",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/gcc/debug/sparkd"
}
},
{
"name": "sparkd-release-clang",
"inherits": "sparkd-release",
"displayName": "Release (clang)",
"description": "Release build compiled w/ clang",
"binaryDir": "${sourceDir}/build/clang/release",
"cacheVariables": {
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -fno-omit-frame-pointer -DNDEBUG -O3",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/clang/release/sparkd"
}
},
{
"name": "sparkd-release-gcc",
"inherits": "sparkd-release",
"displayName": "Release (gcc)",
"description": "Release build compiled w/ gcc",
"binaryDir": "${sourceDir}/build/gcc/release",
"cacheVariables": {
"CMAKE_C_COMPILER": "gcc",
"CMAKE_CXX_COMPILER": "g++",
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -Wno-stringop-overread -Wno-maybe-uninitialized -fno-omit-frame-pointer -DNDEBUG -O3",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/gcc/release/sparkd"
}
},
{
"name": "spark-api-server-base",
"hidden": true,
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_API_SERVER": {
"type": "bool",
"value": "ON"
},
"CONFIG_DEFAULTS_PATH": "config/profiles/md_dev/*.conf;config/profiles/default/*.conf"
}
},
{
"name": "spark-api-server-windows",
"inherits": "spark",
"displayName": "Spark Api Server",
"cacheVariables": {
"BUILD_API_SERVER": {
"type": "bool",
"value": "ON"
}
}
},
{
"name": "spark-api-server-linux",
"inherits": "sparkd",
"displayName": "Spark Api Server",
"generator": "Ninja Multi-Config",
"cacheVariables": {
"BUILD_ADMIN_WEB_APP": {
"type": "BOOL",
"value": "OFF"
},
"BUILD_API_SERVER": {
"type": "bool",
"value": "ON"
},
"BUILD_SPARKD": {
"type": "BOOL",
"value": "OFF"
},
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -DDEBUG",
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -fno-omit-frame-pointer -DNDEBUG -O3",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
"CONFIG_DEFAULTS_PATH": "config/profiles/default/*.conf",
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net8.0"
}
},
{
"name": "sparkd-publish",
"inherits": "sparkd-release-gcc",
"displayName": "Publish",
"description": "Production build compiled w/ gcc and ready to ship"
},
{
"name": "sparkd-ccapi-diag",
"inherits": "sparkd-debug-clang",
"displayName": "Debug (ccapi diag)",
"description": "Debug build w/ ccapi log level 'Trace'",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CCAPI_LOG_LEVEL": "Trace"
}
},
{
"name": "data-stream-suite",
"inherits": "spark",
"displayName": "Data Stream Suite",
"description": "Data Stream utils ported over from Edge",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CONFIG_DEFAULTS_PATH": "config/profiles/default/*.conf;config/profiles/data_stream/*.conf"
}
}
],
"buildPresets": [
{
"name": "spark",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"hidden": true
},
{
"name": "spark-debug",
"displayName": "Debug",
"inherits": "spark",
"configurePreset": "spark",
"configuration": "Debug"
},
{
"name": "spark-release",
"displayName": "Release",
"inherits": "spark",
"configurePreset": "spark",
"configuration": "Release"
},
{
"name": "sparkd",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"hidden": true,
"targets": [
"data_files_dir",
"admin_web_app_bundle",
"install",
"libspark",
"rapidjson_project",
"server_layout",
"sparkd"
]
},
{
"name": "sparkd-debug-clang",
"configurePreset": "sparkd-debug-clang",
"displayName": "Debug (clang)",
"inherits": "sparkd"
},
{
"name": "sparkd-debug-gcc",
"configurePreset": "sparkd-debug-gcc",
"displayName": "Debug (gcc)",
"inherits": "sparkd"
},
{
"name": "sparkd-release-clang",
"configurePreset": "sparkd-release-clang",
"displayName": "Release (clang)",
"inherits": "sparkd"
},
{
"name": "sparkd-release-gcc",
"configurePreset": "sparkd-release-gcc",
"displayName": "Release (gcc)",
"inherits": "sparkd"
},
{
"name": "spark-api-server-windows",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
},
"hidden": true,
"configurePreset": "spark-api-server-windows"
},
{
"name": "spark-api-server-windows-debug",
"displayName": "Spark Api Server (Debug)",
"inherits": "spark-api-server-windows",
"configuration": "Debug"
},
{
"name": "spark-api-server-windows-release",
"displayName": "Spark Api Server (Debug)",
"inherits": "spark-api-server-windows",
"configuration": "Release"
},
{
"name": "spark-api-server-linux",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"hidden": true,
"configurePreset": "spark-api-server-linux"
},
{
"name": "spark-api-server-linux-debug",
"inherits": "spark-api-server-linux",
"displayName": "Spark Api Server (Debug)",
"configuration": "Debug"
},
{
"name": "spark-api-server-linux-release",
"inherits": "spark-api-server-linux",
"displayName": "Spark Api Server (Release)",
"configuration": "Release"
},
{
"name": "sparkd-publish",
"configurePreset": "sparkd-publish",
"displayName": "Publish",
"inherits": "sparkd",
"targets": "install"
},
{
"name": "sparkd-ccapi-diag",
"configurePreset": "sparkd-ccapi-diag",
"displayName": "Debug (ccapi diag)",
"inherits": "sparkd"
},
{
"name": "data-stream-suite-debug",
"displayName": "DataStreamSuite (Debug)",
"configurePreset": "data-stream-suite",
"configuration": "Debug"
},
{
"name": "data-stream-suite-release",
"displayName": "DataStreamSuite (Release)",
"configurePreset": "data-stream-suite",
"configuration": "Release"
}
]
}
+15
View File
@@ -0,0 +1,15 @@
#nusers:
#allow concurrent : true
#expires: 2024-Oct-06 00:00:00 638637696000000000
#generation_time: 2023-Oct-06 18:58:48.015723 5250008173707545134
EncryptedKeyCode {
value {
keycode: "KgoMeiVPzf/kv65GYGCyQQJVY/11sId6LYRwNNlNwA83+sISiSQnOZrziSgxjEAcaAZQn1nV4hY6MRi4XXznvxLYnDKf2bK0yktWWpSSqxqNxbDQ6AVSk5MGHptbsQSGYpYHlyCi0Niv8ES5NTj/FiBJXPrGEZABZBbNkqXIOa0HDdcxY+joeIf32ekX+5/LXN5XDTZBFT2A7q+IPDrFbKzSBvlzGOONSlq+XyKZZPqt0rXGO45V/GxFUTMYiEvn1/72iPGQ715tFXkr9ozGtitonnixzvW8Sfwmu7vM8VpWfoAc9D/1w5m5Ol5BS+Je8wigQysyrC8rud2KU+f7bQ=="
}
}
PublicKey {
value {
key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvvtV/IP1l/F85ME8N8H+\n8TCBOB68Lxd7sdR0geJGssLBq5F22IIlVKylNxiQV3TE6/hmL9dmr8FuUMrjPCal\nvma0axyAdyCMjFH3U0bYzzxnxSWuj5VJIgaZKOVQuX/3Hb+l4RZi7VWZgQFvEJ+F\ny66S2wDu4ey71Mt0yxkMsl5WMZBL3M1z+bt3pKzmBoyIMVLDcV1k1Yr2wspIRriZ\n95er3JWofK1P9s8B3OoqypEopLRW5hJaZN8YRpFNq5VwRUSj83KVobBAQTWDdOA5\nzOkixPVklZFaNyR06iT0gcgZUUM2bjyfQJGQ4GBCZpZb8KPPgtP+WhghoWby9OLv\nKQIDAQAB\n-----END PUBLIC KEY-----"
}
}
+83
View File
@@ -0,0 +1,83 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32922.545
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api", "src\client\spark_api\spark_api.csproj", "{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_core", "src\client\spark_core\spark_core.csproj", "{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_websocket", "src\client\spark_websocket\spark_websocket.csproj", "{3201359D-C071-4089-9EDE-B04D759F1508}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api_server", "src\client\spark_api_server\spark_api_server.csproj", "{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spark_test", "src\client\spark_test\spark_test.csproj", "{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spark.Console", "src\client\Spark.Console\Spark.Console.csproj", "{89D666E6-B500-498F-B026-4D167F68ADFC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
MinSizeRel|x64 = MinSizeRel|x64
Release|x64 = Release|x64
RelWithDebInfo|x64 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|x64.ActiveCfg = Debug|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|x64.Build.0 = Debug|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|x64.Build.0 = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x64.Build.0 = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.Build.0 = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x64.ActiveCfg = Debug|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x64.Build.0 = Debug|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|x64.ActiveCfg = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|x64.Build.0 = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|x64.ActiveCfg = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|x64.Build.0 = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x64.Build.0 = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x64.ActiveCfg = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x64.Build.0 = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x64.ActiveCfg = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x64.Build.0 = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x64.ActiveCfg = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x64.Build.0 = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x64.Build.0 = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x64.ActiveCfg = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x64.Build.0 = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x64.ActiveCfg = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x64.Build.0 = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x64.ActiveCfg = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x64.Build.0 = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x64.Build.0 = Release|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.Debug|x64.ActiveCfg = Debug|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.Debug|x64.Build.0 = Debug|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.MinSizeRel|x64.ActiveCfg = Debug|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.MinSizeRel|x64.Build.0 = Debug|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.Release|x64.ActiveCfg = Release|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.Release|x64.Build.0 = Release|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.RelWithDebInfo|x64.ActiveCfg = Debug|x64
{EFC9FC4D-E92B-4C6D-9B97-26D38EAA118D}.RelWithDebInfo|x64.Build.0 = Debug|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.Debug|x64.ActiveCfg = Debug|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.Debug|x64.Build.0 = Debug|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.MinSizeRel|x64.ActiveCfg = Debug|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.MinSizeRel|x64.Build.0 = Debug|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.Release|x64.ActiveCfg = Release|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.Release|x64.Build.0 = Release|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.RelWithDebInfo|x64.ActiveCfg = Debug|x64
{89D666E6-B500-498F-B026-4D167F68ADFC}.RelWithDebInfo|x64.Build.0 = Debug|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {422D1620-0166-4C26-9A81-CA8A2EB1AB58}
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal
+33
View File
@@ -0,0 +1,33 @@
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=C:/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=false
pull.rebase=false
credential.helper=manager
credential.https://dev.azure.com.usehttppath=true
init.defaultbranch=master
status.short=true
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
submodule.active=.
remote.origin.url=git@bitbucket.org:bluetradesys/spark.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.spark_crypto.dev.remote=origin
branch.spark_crypto.dev.merge=refs/heads/spark_crypto.dev
submodule.docker/linux.url=git@bitbucket.org:bluetradesys/linux_docker.git
submodule.docker/windows.url=git@bitbucket.org:bluetradesys/windows_docker.git
submodule.externals.url=git@bitbucket.org:bluetradesys/externals.git
branch.development.remote=origin
branch.development.merge=refs/heads/development
user.name=John Colvin
user.email=john.colvin@bluetradesys.com
+12
View File
@@ -0,0 +1,12 @@
function(print_list var)
set(CMAKE_MESSAGE_INDENT "")
set(_var_str "")
foreach(item IN LISTS ${var})
set(_var_str "${_var_str}\n ${item}")
endforeach()
if ("${ARGN}" STREQUAL "VERBOSE")
message(VERBOSE "***${var}:${_var_str}")
else()
message("***${var}:${_var_str}")
endif()
endfunction()
-2
View File
@@ -121,8 +121,6 @@ function(Service_Compiler_Generate_Cpp SRCS HDRS)
endforeach()
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
# remove some warnings from protobuf generated files
if(WIN32)
set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS
@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 3.5)
# add protos to the library to facilitate source_group
target_sources(libspark PUBLIC ${Config_Protos} ${NonConfig_Protos} ${Service_Protos})
# Explicitly set policy to convert relative paths to absolute (although this is a default policy,
# setting it explicitly prevents a compile-warning)
cmake_policy(SET CMP0076 NEW)
# add protos to the library to facilitate source_group
target_sources(libspark PUBLIC ${Config_Protos} ${NonConfig_Protos} ${Service_Protos})
function(assign_source_group)
foreach(_source IN ITEMS ${ARGN})
if(IS_ABSOLUTE "${_source}")
+224
View File
@@ -0,0 +1,224 @@
[cmake]: https://cmake.org/
[cmake ext]: https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools
[cmake presets]: https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html
[cpp ext]: https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools
[clangd ext]: https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd
[dotnet]: https://dotnet.microsoft.com/en-us/download/dotnet
[ninja build]: https://ninja-build.org/
[ninja generator]: https://cmake.org/cmake/help/latest/generator/Ninja.html
[ninja multi-config generator]: https://cmake.org/cmake/help/latest/generator/Ninja%20Multi-Config.html
[python]: https://www.python.org/
[py venv]: https://docs.python.org/3/library/venv.html
[visual studio]: https://visualstudio.microsoft.com/
[visual studio generator]: https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2017%202022.html
# C++ Intellisense for Spark on Windows (VS Code)
**Steps**
1. Install the **[C++ extension][cpp ext]**
2. Install the **[CMake extension][cmake ext]**
3. Copy `c_cpp_properties.json` from this folder to `$workspaceFolder/.vscode/`
4. In the VS Code Command Palette, run **CMake: Select Configure Preset**, then
select '**spark**' from the dropdown
**Notes**
* Intellisense won't work for generated files/types until you build libspark
# C++ Intellisense for Sparkd on Linux (VS Code)
1. Install the **[CMake extension][cmake ext]**
2. Install the **[Clangd extension][clangd ext]**
3. (Optional) Install the **[C++ extension][cpp ext]** (*needed for debugging,
but intellisense should work without it*).
4. If the **[C++ extension][cpp ext]** is installed, disable its intellisense in
your workspace settings (*Clangd intellisense is better*)
```
"C_Cpp.intelliSenseEngine": "disabled"
```
5. In the VS Code Command Palette, run **CMake: Select Configure Preset**, then select the
**[preset][cmake presets]** you wish to build from the dropdown
* *The **Clang** presets may work best with the **Clangd** extension*
* *Intellisense won't work for generated files/types until you build libspark*
# Build Spark on Windows
### Dependencies
* **[CMake][cmake]** (version >= 3.23)
* **[Python][python]** (version >= 3.9)
* **[Visual Studio][visual studio]** (2022)
* **[Dotnet][dotnet]** (sdk version >= 7.0.0)
### References
* **[CMakePresets][cmake presets]**
* **[Visual Studio 17 2022 (CMake generator)][visual studio generator]**
* **[Python Virtual Environment][py venv]**
### Notes
* *Run commands from the repo root dir unless otherwise noted*
1. Set up the **[Python virtual environment][py venv]**<br>
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
.venv\bin\activate.bat
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
* *Run commands in python virtual environment*
```
# Configure
cmake --preset spark
# Build Debug
cmake --build --preset spark-debug
dotnet build spark_client.sln --configuration Debug
# Build Release
cmake --build --preset spark-release
dotnet build spark_client.sln --configuration Release
```
# Build Sparkd on Linux
### **Dependencies**
* **[CMake][cmake]** (version >= 3.23)
* **[Ninja Build][ninja build]**
* **[Python][python]** (version >= 3.9)
### **References**
* **[CMakePresets][cmake presets]**
* **[Ninja (CMake generator)][ninja generator]**
* **[Python Virtual Environment][py venv]**
* **[Devcontainer](devcontainer)**
### Prerequisites
* Open repository in a VS Code [Devcontainer](../docker/sparkd/dev/README.md), or
create your own [docker container](../docker/sparkd/dev/README.md) in which to build
### Notes
* *Run commands from the repo root dir unless otherwise noted*<br>
1. Set up the **[Python virtual environment][py venv]**
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
. .venv/bin/activate
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
* *Run commands in python virtual environment*
```
# Configure clang debug
cmake --preset sparkd-clang-debug
# Build clang debug
cmake --build --preset spark-clang-debug
# Configure gcc release
cmake --build --preset sparkd-gcc-release
# Build gcc release
cmake --build --preset sparkd-gcc-release
```
# Build Spark Api Server on Windows
### **Dependencies**
* **[CMake][cmake]** (version >= 3.23)
* **[Python][python]** (version >= 3.9)
* **[Visual Studio][visual studio]** (version)
* **[Dotnet][dotnet]** (sdk version >= 7.0.0)
### **References**
* **[CMakePresets][cmake presets]**
* **[Visual Studio 17 2022 (CMake generator)][visual studio generator]**
* **[Python Virtual Environment][py venv]**
### Notes
* *Run commands from the repo root dir unless otherwise noted*
1. Set up the **[Python Virtual Environment][py venv]**
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
.venv\bin\activate.bat
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
* *Run in python virtual environment*
```
# Configure
cmake --preset spark-api-server-windows
# Build debug
cmake --build --preset spark-api-server-windows-debug
dotnet build Spark.Api.Server.sln --configuration Debug
# Build release
cmake --build --preset spark-api-server-windows-release
dotnet build Spark.Api.Server.sln --configuration Release
```
# Build Spark Api Server on Linux
### **Dependencies**
* **[CMake][cmake]** (version >= 3.23)
* **[Ninja Build][ninja build]**
* **[Python][python]** (version >= 3.9)
* **[Dotnet][dotnet]** (sdk version >= 7.0.0)
### **References**
* **[CMakePresets][cmake presets]**
* **[Ninja Multi-Config (CMake generator)][ninja multi-config generator]**
* **[Python Virtual Environment][py venv]**
### Prerequisites
* Open repository in a VS Code [Devcontainer](../docker/sparkd/dev/README.md), or
create your own [docker container](../docker/sparkd/dev/README.md) in which to build
### Notes
* *Run commands from the repo root dir unless otherwise noted*
1. Set up the **[Python Virtual Environment][py venv]**
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
. .venv/bin/activate
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
* *Run in python virtual environment*
```
# Configure
cmake --preset spark-api-server-linux
# Build debug
cmake --build --preset spark-api-server-linux-debug
dotnet build Spark.Api.Server.sln --configuration Debug
# Build release
cmake --build --preset spark-api-server-linux-release
dotnet build Spark.Api.Server.sln --configuration Release
```
+27
View File
@@ -0,0 +1,27 @@
{
"version": 4,
"configurations": [
{
"name": "Windows",
"intelliSenseMode": "windows-msvc-x64",
"includePath": [
"${workspaceFolder}/src/",
"${workspaceFolder}/build/src/",
"${workspaceFolder}/externals/windows/include/"
],
"defines": ["_WIN32", "__x86_64__"],
"browse": {
"path": [
"${workspaceRoot}/src",
"${workspaceRoot}/build/src"
],
"limitSymbolsToIncludedHeaders": true
},
"cStandard": "c17",
"cppStandard": "c++17",
"configurationProvider": "ms-vscode.cmake-tools",
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.34.31933/bin/Hostx64/x64/cl.exe",
"mergeConfigurations": true
}
]
}
-1
View File
@@ -1 +0,0 @@
set(sources /home/taha/spark/doc/user/build.sh;content/_index.md;content/bts_spark/Glossary/_index.md;content/bts_spark/Help/_index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Launcher/_index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Logging-In-to-the-System/_index.md;content/bts_spark/Logging-In-to-the-System/image3.png;content/bts_spark/Logging-In-to-the-System/image64.png;content/bts_spark/Market/_index.md;content/bts_spark/Market/change_securities.png;content/bts_spark/Market/image11.png;content/bts_spark/Market/image14.png;content/bts_spark/Market/image20.png;content/bts_spark/Market/image21.png;content/bts_spark/Market/image23.png;content/bts_spark/Market/image24.png;content/bts_spark/Market/image34.png;content/bts_spark/Market/image49.png;content/bts_spark/Market/image53.png;content/bts_spark/Market/image66.png;content/bts_spark/Market/image69.png;content/bts_spark/Market/market_view.png;content/bts_spark/Market/settings_icon.png;content/bts_spark/Market/time_and_sales.png;content/bts_spark/My-Windows/_index.md;content/bts_spark/My-Windows/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/Settings/_index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Spreader/_index.md;content/bts_spark/Spreader/image10.png;content/bts_spark/Spreader/image13.png;content/bts_spark/Spreader/image18.png;content/bts_spark/Spreader/image19.png;content/bts_spark/Spreader/image28.png;content/bts_spark/Spreader/image29.png;content/bts_spark/Spreader/image31.png;content/bts_spark/Spreader/image35.png;content/bts_spark/Spreader/image40.png;content/bts_spark/Spreader/image43.png;content/bts_spark/Spreader/image54.png;content/bts_spark/Spreader/image55.png;content/bts_spark/Spreader/image56.png;content/bts_spark/Spreader/image6.png;content/bts_spark/Spreader/image7.png;content/bts_spark/Spreader/image70.png;content/bts_spark/Spreader/image72.png;content/bts_spark/Spreader/image8.png;content/bts_spark/Trading/OrderTypes/index.md;content/bts_spark/Trading/_index.md;content/bts_spark/Trading/algo_studio.png;content/bts_spark/Trading/collapse_all_icon.png;content/bts_spark/Trading/cover_algo_control.png;content/bts_spark/Trading/expand_all_icon.png;content/bts_spark/Trading/image1.png;content/bts_spark/Trading/image17.png;content/bts_spark/Trading/image2.png;content/bts_spark/Trading/image25.png;content/bts_spark/Trading/image27.png;content/bts_spark/Trading/image33.png;content/bts_spark/Trading/image42.png;content/bts_spark/Trading/image44.png;content/bts_spark/Trading/image47.png;content/bts_spark/Trading/image48.png;content/bts_spark/Trading/image5.png;content/bts_spark/Trading/image50.png;content/bts_spark/Trading/image52.png;content/bts_spark/Trading/image57.png;content/bts_spark/Trading/image59.png;content/bts_spark/Trading/image60.png;content/bts_spark/Trading/image61.png;content/bts_spark/Trading/image62.png;content/bts_spark/Trading/image73.png;content/bts_spark/Trading/image74.png;content/bts_spark/Trading/join_algo_control.png;content/bts_spark/Trading/ladder.png;content/bts_spark/Trading/ladder_badges.png;content/bts_spark/Trading/ladder_main_part.png;content/bts_spark/Trading/lean_algo_control.png;content/bts_spark/Trading/mini_orderbook.png;content/bts_spark/Trading/oco_algo_control.png;content/bts_spark/Trading/offset_algo_control.png;content/bts_spark/Trading/pnl_calculation.png;content/bts_spark/Trading/pnl_window.png;content/bts_spark/Trading/recreate_icon.png;content/bts_spark/Trading/settings_icon.png;content/bts_spark/Trading/spark_menu_order_book.png;content/bts_spark/Trading/top_algo_control.png;content/bts_spark/Trading/trigger_algo_control.png;content/bts_spark/_index.md;content/release_notes/_index.md;content/system_requirements/_index.md;static/book.js;static/favicon.ico;static/image.js;templates/index.html;templates/page.html;templates/section.html;templates/shortcodes/back_button.html)
Submodule docker/linux deleted from 6537812262.
+125
View File
@@ -0,0 +1,125 @@
FROM ubuntu:latest
ARG DEBIAN_FRONTEND=noninteractive
# Light Deps - should be quick to download/install.
# Longer running procs should be executed in individual RUNs.
RUN apt-get update && apt-get install -y \
build-essential \
ca-certificates \
curl \
gnupg \
liblttng-ust-dev \
libpcap0.8-dev \
locales \
ninja-build \
software-properties-common \
sqlite3 \
tzdata
# Clang 17
RUN \
curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key 2> /dev/null \
| gpg --dearmor - \
| tee /usr/share/keyrings/llvm-snapshot.gpg > /dev/null \
&& echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main" \
| tee -a "/etc/apt/sources.list.d/llvm.list" \
&& apt-get update \
&& apt-get install -y \
clang-17 \
clang-format-17 \
clangd-17
# G++
RUN apt-get update && apt-get install -y \
g++
# Python
RUN apt-get update && apt-get install -y \
python3-pip \
python3-venv \
&& python3 -m pip install --upgrade pip
# Dotnet
RUN \
curl -fsSLO "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" \
&& dpkg -i packages-microsoft-prod.deb \
&& rm packages-microsoft-prod.deb \
&& apt-get update \
&& apt-get install -y dotnet-sdk-8.0
# SSH
RUN apt-get update && apt-get install -y \
libssh2-1-dev \
openssh-server
# CMake
RUN \
curl -fsSL https://apt.kitware.com/keys/kitware-archive-latest.asc 2> /dev/null \
| gpg --dearmor - \
| tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \
&& echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" \
| tee /etc/apt/sources.list.d/kitware.list > /dev/null \
&& apt-get update \
&& apt-get install -y cmake
# Node
ARG node_major=18
RUN mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$node_major.x nodistro main" \
| tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs
# Dev Utils
RUN apt-get update && apt-get install -y \
ccache \
fish \
gdb \
git-all \
sudo \
vim
# Set up default executables (update-alternatives)
RUN \
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 100; \
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100; \
update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-17 100; \
update-alternatives --install /usr/bin/clangd clangd /usr/bin/clangd-17 100; \
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100; \
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100
# Add compiler symlinks for ccache
RUN \
ln -s /usr/bin/ccache /usr/local/bin/clang; \
ln -s /usr/bin/ccache /usr/local/bin/clang++; \
ln -s /usr/bin/ccache /usr/local/bin/clang-13; \
ln -s /usr/bin/ccache /usr/local/bin/clang++-13; \
ln -s /usr/bin/ccache /usr/local/bin/clang-15; \
ln -s /usr/bin/ccache /usr/local/bin/clang++-15; \
ln -s /usr/bin/ccache /usr/local/bin/clang-17; \
ln -s /usr/bin/ccache /usr/local/bin/clang++-17; \
ln -s /usr/bin/ccache /usr/local/bin/gcc; \
ln -s /usr/bin/ccache /usr/local/bin/g++; \
ln -s /usr/bin/ccache /usr/local/bin/gcc-11; \
ln -s /usr/bin/ccache /usr/local/bin/g++-11; \
ln -s /usr/bin/ccache /usr/local/bin/gcc-12; \
ln -s /usr/bin/ccache /usr/local/bin/g++-12
RUN locale-gen en_US.UTF-8
ARG docker_user="bts"
ARG docker_uid="1000"
ARG docker_pass="bts"
RUN \
groupadd -g "$docker_uid" "$docker_user" \
&& useradd \
-m \
-u "$docker_uid" \
-g "$docker_uid" \
-G sudo \
--password "$(openssl passwd -1 "$docker_pass")" \
"$docker_user"
+64
View File
@@ -0,0 +1,64 @@
[dev containers]: https://code.visualstudio.com/docs/devcontainers/containers
[dev containers ext]: https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers
[docker repo sparkd-dev]: https://hub.docker.com/repository/docker/bluetradingsystems/sparkd-dev/general
# Sparkd Dev Container
## How to create a VS Code [Dev Container][dev containers]
1. Make sure the **[Dev Containers][dev containers ext]** extension is installed
1. Make sure your Docker image is up to date
```
docker pull bluetradingsystems/sparkd-dev:latest
```
1. Copy **devcontainer.json** from this folder to **$workspaceFolder/.devcontainer/**.
1. In the VS Code Command Palette, run **Dev Containers: Reopen in Container**
---
## How to create a Sparkd Container in the terminal (without VS Code)
1. Make sure your Docker image is up to date
```
docker pull bluetradingsystems/sparkd-dev:latest
```
2. Start the container
```
# Replace <cont_name> with a name for the container. The container's
# "$HOME" dir will be mounted to "$HOME/.sparkd-dev/mounts/<cont_name> on
# the host
./start_docker.sh --container <cont_name> --mount-existing
```
* *Replace <cont_name> with a name for the container*
* *The container's `$HOME` dir will be mounted to
`$HOME/.sparkd-dev/mounts<cont_name>` on the host*<br>
* *Run: `./start_docker.sh --help` to see additional options*
3. *(Optional) Attach VS Code to the running container.*<br>
Run **Dev Containers: Attach to Running Container** from the command palette,
then select your container in the dropdown
---
## How to update the Docker image
1. Change the image by modifying the Dockerfile (don't tag arbitrary
images on your machine and push them to our repo on Docker Hub)
1. After modifying the Dockerfile, (re)build the image
```
# Run in this dir
docker build -t bluetradingsystems/sparkd-dev:latest .
```
***Note:** Your docker login must have write permissions to push to the
[sparkd-dev][docker repo sparkd-dev] repository*
2. Commit the changes to Dockerfile in git
3. Push the new image to Docker Hub
```
docker push bluetradingsystems/sparkd-dev:latest
```
***Note:** The image doesn't have to be on Docker Hub, we can simply build
it from scratch on our local machines (with the Dockerfile). However, this
takes time. It is significantly quicker to download a prebuilt image, so we
store it on a remote repository to save time when setting up a new dev
machine.*
+123
View File
@@ -0,0 +1,123 @@
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
if [[ ! -v XDG_CONFIG_HOME ]]; then
export XDG_CONFIG_HOME="$HOME/.config"
fi
export PATH="$HOME/.local/bin:$PATH"
+25
View File
@@ -0,0 +1,25 @@
if ! set -q XDG_CONFIG_HOME
set -g XDG_CONFIG_HOME "$HOME/.config"
end
set fish_config_home $XDG_CONFIG_HOME/fish
if test -f "$fish_config_home/aliases.fish"
source "$fish_config_home/aliases.fish"
end
# enable general colors and case insensitive search in 'less'
set -x LESS "$LESS -R -Q -I"
set -x LC_ALL en_US.UTF-8
# enable syntax highlighting in 'less'
# set highlight color scheme in 'less' (fg)(bg)
set -g LESS_TERMCAP_md (tput bold)(tput setaf 36)
set -g LESS_TERMCAP_me (tput sgr0)
set -g LESS_TERMCAP_so (tput setaf 232)(tput setab 49)
set -q TERM
if test $status != 0; or test $TERM = 'xterm'
set -g TERM 'xterm-256color'
end
# Fix impossible-to-see navy blue command text color
set fish_color_command F8F8F2
set -g PATH "$HOME/.local/bin" "$PATH"
+33
View File
@@ -0,0 +1,33 @@
{
"image": "bluetradingsystems/sparkd-dev:latest",
// Creates local dir to mount to HOME in docker
"initializeCommand": "mkdir -p ${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId}",
"hostRequirements": {
"memory": "4gb",
"storage": "6gb"
},
"postCreateCommand": "/home/bts/spark/docker/sparkd/dev/devcontainer_post_create.sh",
"containerUser": "bts",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/bts/spark,type=bind",
"workspaceFolder": "/home/bts/spark",
"updateRemoteUserUID": true,
"shutdownAction": "none",
// Note: If running multiple containers on the same host, each must use a
// unique set of ports. Usually we just add 1000 to each port as needed. For
// example, if 8000-8003 is taken, go with 9000-9003, then 10000-10003, etc.
"runArgs": [
"--shm-size",
"2gb",
"-p",
"8000:8000",
"-p",
"8001:8001",
"-p",
"8002:8002",
"-p",
"8003:8003"
],
"mounts": [
"source=${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId},target=/home/bts,type=bind"
]
}
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
this_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
repo_dir="$(cd "$this_dir" && git rev-parse --show-toplevel)"
tools_dir="$repo_dir/tools"
gen_tag="GENERATED BY $(basename "${BASH_SOURCE[0]}")"
function copy_if_not_exist() {
src="$1"
dest="$2"
if [[ ! -e "$src" ]]; then
echo "Unable to copy $src to $dest. Source file doesn't exist"
exit 1
fi
if [[ ! -e "$dest" ]]; then
cp "$src" "$dest"
fi
}
# Init bashrc
echo "Initializing bashrc"
copy_if_not_exist "$this_dir/bashrc" "$HOME/.bashrc"
# Init fish config
echo "Initializing fish config"
fish_cfg_dir="$HOME/.config/fish/"
mkdir -p "$fish_cfg_dir"
exec "$tools_dir/write_tag_block.sh" \
--tag "$gen_tag" \
--replace \
--in-place \
--file "$fish_cfg_dir/config.fish" \
--text "$(cat "$this_dir/config.fish")"
+250
View File
@@ -0,0 +1,250 @@
#!/usr/bin/env bash
function _exit() {
if [[ "$#" -gt 1 ]]; then
# When there are multiple args, the last arg is the exit code.
echo "${@:1:($# - 1)}"
exit "${@: -1}"
fi
echo "$1"
exit 0
}
help_text="\
Add or update a user's uid
This script is intended to be run in a Docker container as a means to obtain
file permissions in mounted directories owned by the specified UID.
Usage: set_user.sh [OPTIONS] USER UID
Positionals:
USER The name of the user
Options:
--user USER The name of the user (defaults to 'bts')
--uid UID The new uid to give USER (defaults to '1000')
--group GROUP The primary group to give USER (defaults to USER)
--gid GID The primary gid to give USER (defaults to UID)
--pass PASSWORD The password to give USER (defaults to USER, only applies
if USER hasn't been created yet)
--modify-existing Update UID/GID even if USER already exists
-h,--help Print this help message and exit
"
function _add_group() {
if [[ "$#" -ne 2 ]]; then
_exit "'_add_group' requires exactly 2 args (group, gid). Received $#." 1
fi
local group="$1"
local gid="$2"
# Check if gid already exists
local existing_group=""
existing_group="$(getent group "$gid" | cut -d : -f 1)"
if [[ -n "$existing_group" ]]; then
if [[ "$existing_group" != "$group" ]]; then
echo "\
The gid '$gid' is already in use by group '$existing_group' (will not rename \
the group)"
fi
return
fi
# Check if group with same name already exists
local existing_gid=""
existing_gid="$(getent group "$group" | cut -d : -f 3)"
if [[ -n "$existing_gid" ]]; then
# The group already exists. Only modify if --modify-existing was specified.
if [[ "$modify_existing" -eq 0 ]]; then
_exit "\
The group '$group' already exists with gid '$existing_gid'.
Specify --modify-existing to change the gid anyways." 1
fi
echo "Changing gid for group '$group' from '$existing_gid' to '$gid'"
groupmod -g "$gid" "$group"
else
# The group doesn't exist. Add it
echo "Adding group '$group:$gid'"
groupadd -g "$gid" "$group"
fi
}
function _add_user() {
local user="$1"
local uid="$2"
local group="$3"
local gid="$4"
local pass="$5"
if [[ "$#" -ne 5 ]]; then
_exit "'_add_user' requires exactly 5 args (user, uid, group, gid, pass). \
Received $#." 1
fi
# Check if uid is being used by another user
local existing_user=""
existing_user="$(getent passwd "$uid" | cut -d : -f 1)"
if [[ -n "$existing_user" ]]; then
if [[ "$existing_user" != "$user" ]]; then
_exit "The uid '$uid' is already in use by user '$existing_user'." 1
fi
echo "The user '$user' already has the specified uid '$uid'."
# Modify gid if necessary
local existing_gid=""
existing_gid="$(id -g "$user" 2> /dev/null)"
if [[ "$existing_gid" = "$gid" ]]; then
echo "The user '$user' already has the specified gid '$gid'."
return
fi
if [[ "$modify_existing" -eq 0 ]]; then
_exit "\
The user '$user' is associated with the primary group '$existing_gid'.
Specify --modify-existing to change the gid anyways." 1
fi
echo "Changing primary group for '$user' from '$existing_gid' to '$gid'."
usermod -g "$gid" "$user"
return
fi
# Check if user with same name already exists
local existing_uid=""
existing_uid="$(id -u "$user" 2> /dev/null)"
if [[ -n "$existing_uid" ]]; then
if [[ "$existing_uid" = "$uid" ]]; then
_exit "The user '$user' already has the specified uid '$uid'" 0
fi
if [[ "$modify_existing" -eq 0 ]]; then
_exit "\
User '$user' already exists with uid '$existing_uid'.
Specify --modify-existing to change the uid anyways." 1
fi
echo "Changing uid for user '$user' from '$existing_uid' to '$uid'"
if ! usermod -u "$uid" -g "$gid" "$user"; then
_exit "usermod exited with code $?" 1
fi
return
fi
# The user doesn't exist. Add it
echo "Adding user '$user:$uid' (group='$group:$gid', password='$pass')"
useradd -m -u "$uid" -g "$gid" -G sudo --password "$(openssl passwd -1 "$pass")" "$user"
}
function _update_fish_dir_perms() {
local user="$1"
local uid="$2"
local gid="$3"
# When a fish shell session starts, a temp dir named '/tmp/fish.<user>' is
# created with the user's current uid/gid. If such a dir exists for the
# specified USER, make sure the uid/gid match the new values.
fish_dir="/tmp/fish.$user"
if [[ -d "$fish_dir" ]]; then
perms="$uid:$gid"
existing_perms="$(stat -c %u:%g "$fish_dir")"
if [[ "$existing_perms" != "$perms" ]]; then
echo "Changing uid:gid for dir '$fish_dir' from '$existing_perms' to '$perms'"
chown -R "$perms" "$fish_dir"
fi
fi
}
user=""
group=""
pass=""
declare -i uid=0
declare -i gid=0
declare -i modify_existing=0
while [[ $# -gt 0 ]]; do
case "$1" in
--user)
if [[ -z "$2" ]]; then
_exit "USER (--user) must be non-empty" 1
elif [[ "$2" = "root" ]]; then
_exit "USER (--user) cannot be 'root'" 1
fi
user="$2"
shift 2
;;
--group)
if [[ -z "$2" ]]; then
_exit "GROUP (--group) must be non-empty" 1
elif [[ "$2" = "root" ]]; then
_exit "GROUP (--group) cannot be 'root'" 1
fi
group="$2"
shift 2
;;
--uid)
if [[ -z "$2" ]]; then
_exit "UID (--uid) must be non-empty" 1
fi
uid="$2"
shift 2
;;
--gid)
if [[ -z "$2" ]]; then
_exit "GID (--gid) must be non-empty" 1
fi
gid="$2"
shift 2
;;
--pass)
if [[ -z "$2" ]]; then
_exit "PASS (--pass) must be non-empty" 1
fi
pass="$2"
shift 2
;;
--modify-existing)
modify_existing=1
shift 1
;;
-h)
;&
--help)
_exit "$help_text" 0
;;
*)
if [[ -z "$1" ]]; then
_exit "Invalid positional argument '$1'" 1
elif [[ -z "$user" ]]; then
user="$1"
elif [[ -z "$uid" ]]; then
uid="$1"
else
_exit "Unexpected argument '$1'" 1
fi
shift 1
;;
esac
done
if [[ -z "$user" ]]; then
user="bts"
fi
if [[ $uid -eq 0 ]]; then
uid=1000
fi
# In general, a user's primary group/gid matches the user's name/uid.
# If group/gid args weren't specified, set them to name/uid.
if [[ -z "$group" ]]; then
group="$user"
fi
if [[ $gid -eq 0 ]]; then
gid=$uid
fi
if [[ -z "$pass" ]]; then
pass="$user"
fi
_add_group "$group" "$gid"
_add_user "$user" "$uid" "$group" "$gid" "$pass"
_update_fish_dir_perms "$user" "$uid" "$gid"
+230
View File
@@ -0,0 +1,230 @@
#!/usr/bin/env bash
function _exit() {
if [[ "$#" -gt 1 ]]; then
# When there are multiple args, the last arg is the exit code.
echo "${@:1:($# - 1)}"
exit "${@: -1}"
fi
echo "$1"
exit 0
}
help_text="\
Start a docker dev container
Usage: start_docker.sh [OPTIONS] image container
Positionals:
image The image to instantiate
container The name for the container
Options:
-u,--user USER The user to add in the container (defaults to 'bts')
-p,--pass PASS The password for USER in the container (defaults to USER)
-i,--image IMAGE The image to instantiate (defaults to 'bluetradingsystems/sparkd-dev:latest')
-c,--container CONT The name for the container
-m,--mount MOUNT The name for the folder (outside the container) to create/mount to the home
directory in the container. Mount folders are added here: $mount_prefix
--mount-existing Mount the specified dir even if it already exists
--port <cont_port>:<host_port> OR [<cont_port>:<host_port>,...] Port mapping(s). May be
specified multiple times.
-h,--help Print this help message and exit
"
mount_prefix="$HOME/.sparkd-dev/mounts"
declare docker_user=""
declare docker_pass=""
declare image_name=""
declare cont_name=""
declare mount_name=""
declare -i mount_existing=0
declare -a port_mappings=()
while [[ $# -gt 0 ]]; do
case "$1" in
-u)
;&
--user)
if [[ -z "$2" ]]; then
_exit "User (-u,--user) must be non-empty" 1
fi
docker_user="$2"
shift 2
;;
-p)
;&
--pass)
if [[ -z "$2" ]]; then
_exit "Password (-p,--pass) must be non-empty" 1
fi
docker_pass="$2"
shift 2
;;
-i)
;&
--image)
if [[ -n "$image_name" ]]; then
_exit "Unexpected argument '$1'" 1
elif [[ -z "$2" ]]; then
_exit "Image (-i,--image) must be non-empty" 1
fi
image_name="$2"
shift 2
;;
-c)
;&
--container)
if [[ -n "$cont_name" ]]; then
_exit "Unexpected argument '$1'" 1
elif [[ -z "$2" ]]; then
_exit "Container (-c,--container) must be non-empty" 1
fi
cont_name="$2"
shift 2
;;
--port)
# Parse port(s) arg, and append the result to 'port_mappings'
# Note: port(s) may be specified in bracketed notation:
# [a:b,c:d,...,y:z]
next_ports="$(echo "$2" | sed -e 's/\[//g' -e 's/\]//g' -e 's/,/ /g')"
if [[ "${#port_mappings[@]}" -gt 0 ]]; then
next_ports=" $next_ports"
fi
port_mappings+=("$next_ports")
shift 2
;;
-m)
;&
--mount)
if [[ -z "$2" ]]; then
echo "Mount (-m,--mount) must be non-empty"
fi
mount_name="$2"
shift 2
;;
--mount-existing)
mount_existing=1
shift 1
;;
-h)
;&
--help)
_exit "$help_text" 0
;;
*)
if [[ -z "$1" ]]; then
_exit "Invalid positional argument '$1'" "$help_text" 1
elif [[ -z "$image_name" ]]; then
image_name="$1"
elif [[ -z "$cont_name" ]]; then
cont_name="$1"
else
_exit "Unexpected argument '$1'" "$help_text" 1
fi
shift 1
;;
esac
done
if [[ -z "$image_name" ]]; then
image_name="bluetradingsystems/sparkd-dev:latest"
fi
host_name="$(hostname)"
if [[ -n "$cont_name" ]]; then
host_name="$host_name.$cont_name"
fi
if [[ -z "$mount_name" ]]; then
mount_name="$cont_name"
fi
if [[ -z "$mount_name" && -z "$cont_name" ]]; then
_exit "Please specify mount (-m,--mount) and/or container (-c,--container)" 1
fi
if [[ -z "$docker_user" ]]; then
docker_user="bts"
fi
if [[ "$docker_user" = "root" ]]; then
_exit "USER (--user) cannot be 'root'" 1
fi
cont_home="/home/$docker_user"
home_src="$mount_prefix/$mount_name"
home_tgt="$cont_home"
this_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
repo_src="$(cd "$this_dir" && git rev-parse --show-toplevel)"
repo_tgt="$cont_home/spark"
working_dir="$cont_home"
if [[ $mount_existing -eq 0 && -e "$home_src" ]]; then
# Don't overwrite existing dir (might be mounted in another container)
_exit "Mount dir '$home_src' already exists (use --mount-existing to mount \
an existing directory)" 1
fi
mkdir -p "$home_src"
if [[ "${#port_mappings[@]}" -eq 0 ]]; then
port_mappings=("8000:8000" "8001:8001" "8002:8002" "8003:8003")
fi
# Adapt port_mappings into args for `docker run` by prepending "-p " to each
# item
declare -a docker_port_args=()
for port_mapping in "${port_mappings[@]}"; do
docker_port_args+=("-p $port_mapping")
done
echo "Starting container '$cont_name'
image_name : $image_name
cont_name : $cont_name
home_src : $home_src
home_tgt : $home_tgt
repo_src : $repo_src
repo_tgt : $repo_tgt
working dir : $working_dir
ports : ${port_mappings[*]}
"
# DON'T wrap $docker_port_args in quotes. We want bash to split args by
# whitespace
docker run \
--net bridge \
-h "$host_name" \
-e "TZ=America/New_York" \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
--name "$cont_name" \
-v "$home_src:$home_tgt" \
-v "$repo_src:$repo_tgt" \
-w "$working_dir" \
${docker_port_args[*]} \
--shm-size=4024m \
-t \
-i \
-d \
-e DISPLAY="$DISPLAY" \
"$image_name"
# Add user w/ same uid and gid as the current user outside of docker, so the
# user inside the docker has file permissions in the mounted dir.
docker_group="$docker_user"
docker_uid="$(id -u "$USER")"
docker_gid="$(id -g "$USER")"
if [[ -z "$docker_pass" ]]; then
docker_pass="$docker_user"
fi
docker exec -u root -it "$cont_name" "$repo_tgt/docker/sparkd/dev/set_user.sh" \
--user "$docker_user" \
--uid "$docker_uid" \
--group "$docker_group" \
--gid "$docker_gid" \
--pass "$docker_pass"
# Run same script VS Code runs to initialize the container
docker exec -u "$docker_user" -it "$cont_name" "$repo_tgt/docker/sparkd/dev/devcontainer_post_create.sh"
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
function print_help_and_exit() {
cat <<EOF
Open a shell inside the docker container
Usage: docker_shell.sh [OPTIONS] [CONTAINER]
Options:
-u,--user The user to login with in the container (defaults to the current user)
-c,--container The container name (may also be specified as positional arg)
-h,--help Print this help message and exit
EOF
exit "$1"
}
declare docker_user=""
declare cont_name=""
while [[ $# -gt 0 ]]; do
case "$1" in
-u)
;&
--user)
if [[ -z "$2" ]]; then
echo "User (-u,--user) must be non-empty"
print_help_and_exit 1
fi
docker_user="$2"
shift 2
;;
-h)
;&
--help)
print_help_and_exit 0
;;
-c)
;&
--container)
shift 1
;&
*)
if [[ ! -z "$cont_name" ]]; then
echo "Unexpected argument '$1'"
print_help_and_exit 1
fi
cont_name="$1"
shift 1
;;
esac
done
if [[ -z "$cont_name" ]]; then
echo "Please specify the container ([-c,--container])"
print_help_and_exit 1
fi
if [[ -z "$docker_user" ]]; then
docker_user="$USER"
fi
docker exec -u "$docker_user" -it "$cont_name" bash
+233
View File
@@ -0,0 +1,233 @@
#!/usr/bin/env bash
mount_prefix="$HOME/.spark-dev/mounts"
function print_help_and_exit() {
cat <<EOF
Start a docker dev container
Usage: start_docker.sh [OPTIONS] image container
Positionals:
image The image to instantiate
container The name for the container
Options:
-u,--user USER The user to add in the container (defaults to the current user)
-p,--pass PASS The password for USER in the container (defaults to USER)
-i,--image IMAGE The image to instantiate
-c,--container CONT The name for the container
-m,--mount MOUNT The name for the folder (outside the container) to create/mount to the home
directory in the container. Mount folders are added here: $mount_prefix
--mount-existing Mount the specified dir even if it already exists
--port <cont_port>:<host_port> OR [<cont_port>:<host_port>,...] Port mapping(s). May be
specified multiple times.
-h,--help Print this help message and exit
EOF
exit "$1"
}
declare docker_user=""
declare docker_pass=""
declare image_name=""
declare cont_name=""
declare mount_name=""
declare -i mount_existing=0
declare -a port_mappings=()
while [[ $# -gt 0 ]]; do
case "$1" in
-u)
;&
--user)
if [[ -z "$2" ]]; then
echo "User (-u,--user) must be non-empty"
print_help_and_exit 1
fi
docker_user="$2"
shift 2
;;
-p)
;&
--pass)
if [[ -z "$2" ]]; then
echo "Password (-p,--pass) must be non-empty"
print_help_and_exit 1
fi
docker_pass="$2"
shift 2
;;
-i)
;&
--image)
if [[ -n "$image_name" ]]; then
echo "Unexpected argument '$1'"
print_help_and_exit 1
elif [[ -z "$2" ]]; then
echo "Image (-i,--image) must be non-empty"
print_help_and_exit 1
fi
image_name="$2"
shift 2
;;
-c)
;&
--container)
if [[ -n "$cont_name" ]]; then
echo "Unexpected argument '$1'"
print_help_and_exit 1
elif [[ -z "$2" ]]; then
echo "Container (-c,--container) must be non-empty"
print_help_and_exit 1
fi
cont_name="$2"
shift 2
;;
--port)
# Parse port(s) arg, and append the result to 'port_mappings'
# Note: port(s) may be specified in bracketed notation:
# [a:b,c:d,...,y:z]
next_ports="$(echo "$2" | sed -e 's/\[//g' -e 's/\]//g' -e 's/,/ /g')"
if [[ "${#port_mappings[@]}" -gt 0 ]]; then
next_ports=" $next_ports"
fi
port_mappings+=("$next_ports")
shift 2
;;
-m)
;&
--mount)
if [[ -z "$2" ]]; then
echo "Mount (-m,--mount) must be non-empty"
fi
mount_name="$2"
shift 2
;;
--mount-existing)
mount_existing=1
shift 1
;;
-h)
;&
--help)
print_help_and_exit 0
;;
*)
if [[ -z "$1" ]]; then
echo "Invalid positional argument '$1'"
print_help_and_exit 1
elif [[ -z "$image_name" ]]; then
image_name="$1"
elif [[ -z "$cont_name" ]]; then
cont_name="$1"
else
echo "Unexpected argument '$1'"
print_help_and_exit 1
fi
shift 1
;;
esac
done
if [[ -z "$image_name" ]]; then
image_name="bluetradingsystems/spark-crypto-dev"
fi
host_name="$(hostname)"
if [[ -n "$cont_name" ]]; then
host_name="$host_name.$cont_name"
fi
if [[ -z "$mount_name" ]]; then
mount_name="$cont_name"
fi
if [[ -z "$mount_name" && -z "$cont_name" ]]; then
echo "Please specify mount (-m,--mount) and/or container (-c,--container)"
print_help_and_exit 1
fi
if [[ -z "$docker_user" ]]; then
docker_user="$USER"
fi
home_src=$mount_prefix/$mount_name
home_tgt=$HOME
repo_src=$(git rev-parse --show-superproject-working-tree)
repo_tgt=$HOME/$(basename "$repo_src")
working_dir=$HOME
if [[ $mount_existing -eq 0 && -e "$home_src" ]]; then
# Don't overwrite existing dir (might be mounted in another container)
echo "Mount dir '$home_src' already exists (use --mount-existing to mount an existing directory)"
print_help_and_exit 1
fi
mkdir -p "$home_src"
if [[ "${#port_mappings[@]}" -eq 0 ]]; then
port_mappings=("8000:8000" "8001:8001" "8002:8002" "8003:8003")
fi
# Adapt port_mappings into args for `docker run` by prepending "-p " to each
# item
declare -a docker_port_args=()
for port_mapping in "${port_mappings[@]}"; do
docker_port_args+=("-p $port_mapping")
done
echo "Starting container '$cont_name'
image_name : $image_name
cont_name : $cont_name
home_src : $home_src
home_tgt : $home_tgt
repo_src : $repo_src
repo_tgt : $repo_tgt
working dir : $working_dir
ports : ${port_mappings[*]}
"
# DON'T wrap $docker_port_args in quotes. We want bash to split args by
# whitespace
docker run \
--net bridge \
-h "$host_name" \
-e "TZ=America/New_York" \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
--name "$cont_name" \
-v "$home_src:$home_tgt" \
-v "$repo_src:$repo_tgt" \
-w "$working_dir" \
${docker_port_args[*]} \
--shm-size=4024m \
-t \
-i \
-d \
-e DISPLAY="$DISPLAY" \
"$image_name" \
bash
# Add user w/ same uid and gid as the current user outside of docker, so the
# user inside the docker has file permissions in the mounted dir.
docker_group="$docker_user"
docker_user_uid="$(id -u "$USER")"
docker_user_gid="$(id -g "$USER")"
echo "Adding user in container '$cont_name'
name : $docker_user
uid : $docker_user_uid
gid : $docker_user_gid"
if [[ -z "$docker_pass" ]]; then
docker_pass="$docker_user"
echo "Giving user '$docker_user' a secure password: $docker_pass"
fi
docker exec -u root -it "$cont_name" groupadd -g "$docker_user_gid" "$docker_group"
docker exec -u root -it "$cont_name" useradd -u "$docker_user_uid" -g "$docker_user_gid" "$docker_user"
docker exec -u root -it "$cont_name" usermod --password "$(openssl passwd -1 "$docker_pass")" "$docker_user"
docker exec -u root -it "$cont_name" usermod -aG sudo "$docker_user"
docker exec -u root -it "$cont_name" "$repo_tgt/externals/src/emumba/install_emumba-deribit-connector.sh"
Submodule docker/windows deleted from de7d40c09d.
+45
View File
@@ -0,0 +1,45 @@
# import json
# from rauth import OAuth2Service
# class ExampleOAuth2Client:
# def __init__(self, url, path, client_id, client_secret):
# self.access_token = None
# self.service = OAuth2Service(
# name="foo",
# client_id=client_id,
# client_secret=client_secret,
# access_token_url=f'{url}{path}',
# authorize_url=f'{url}{path}',
# base_url=url,
# )
# self.get_access_token()
# def get_access_token(self):
# data = {
# 'grant_type': 'client_credentials', # generally required!
# }
# session = self.service.get_auth_session(data=data, decoder=json.loads)
# self.access_token = session.access_token
# def _main():
# client_id = 'API_THINKALPHA123'
# client_secret = '$MM9Rn*#qYARY$$QTMA#AMn*'
# oath = ExampleOAuth2Client(
# url='https://authnr.cmegroup.com',
# path='/as/token.oath2',
# client_id=client_id,
# client_secret=client_secret,
# )
# tok = oath.get_access_token()
# print(tok)
# if __name__ == '__main__':
# try:
# _main()
# except json.JSONDecodeError as jde:
# print(f'get-token.py failed with json-decode-error: {jde}.\n{jde.doc}\n\nlineno: {jde.lineno}\npos: {jde.pos}')
# except Exception as e:
# print(f'get-token.py failed: {e}')
+30
View File
@@ -0,0 +1,30 @@
import subprocess
def _main():
host = "markets.api.uat.cmegroup.com"
port = "443"
# AUTH_ENDPOINT="$host/marketdatastream/v1"
AUTH_ENDPOINT = 'https://authnr.cmegroup.com/as/token.oauth2'
API_KEY = "API_THINKALPHA123"
API_SECRET = '$MM9Rn*#qYARY$$QTMA#AMn*'
# Define your API key and secret
# API_KEY="YOUR_API_KEY"
# API_SECRET="YOUR_API_SECRET"
# Define the authentication API endpoint URL
# AUTH_ENDPOINT="https://api.example.com/auth"
# Perform the POST request and capture the response
# response=$(curl -s -X POST -d "api_key=$API_KEY&api_secret=$API_SECRET&grant_type=password&username=API_THINKALPHA123&password=$API_SECRET" "$AUTH_ENDPOINT")
# subprocess.run('ls')
subprocess.run(
f'curl -s -X POST -d "grant_type=client_credentials&client_id={API_KEY}&client_secret={API_SECRET}" "{AUTH_ENDPOINT}"',
)
# curl --user 'API_THINKALPHA123:$MM9Rn*#qYARY$$QTMA#AMn*' 'https://query-api.datamine.cmegroup.com/v3/query/query_order_record?tradedate=2023-07-10&fields=symbol,transacttime,instrumentsequencenumber,tradeprice,tradequantity,tradeflag&q=asset.eq.TN,securitytype.eq.FUT,tradeflag.nin.OBS&fileFormat=csv&securityexchange=XCBT&underlyingproduct=Interest%20Rate'
if __name__ == '__main__':
_main()
View File
Whitespace-only changes.
+211
View File
@@ -0,0 +1,211 @@
[cmake]: https://cmake.org/
[cmake ext]: https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools
[cmake presets]: https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html
[clangd ext]: https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd
[cpp ext]: https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools
[docker]: https://www.docker.com/
[dotnet]: https://dotnet.microsoft.com/en-us/download/dotnet
[ninja build]: https://ninja-build.org/
[ninja generator]: https://cmake.org/cmake/help/latest/generator/Ninja.html
[ninja multi-config generator]: https://cmake.org/cmake/help/latest/generator/Ninja%20Multi-Config.html
[python]: https://www.python.org/
[py venv]: https://docs.python.org/3/library/venv.html
[visual studio]: https://visualstudio.microsoft.com/
[visual studio generator]: https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2017%202022.html
[devcontainer]: https://code.visualstudio.com/docs/devcontainers/create-dev-container
# C++ Intellisense for Spark on Windows (VS Code)
**Steps**
1. Install the **[C++ extension][cpp ext]**
2. Install the **[CMake extension][cmake ext]**
3. Copy `c_cpp_properties.json` from this folder to `$workspaceFolder/.vscode/`
4. In the VS Code Command Palette, run `CMake: Select Configure Preset`, then
select '**spark**' from the dropdown
**Notes**
* Intellisense won't work for generated files/types until you build libspark
# C++ Intellisense for Sparkd on Linux (VS Code)
1. Install the **[CMake extension][cmake ext]**
2. Install the **[Clangd extension][clangd ext]**
3. (Optional) Install the **[C++ extension][cpp ext]** (*needed for debugging,
but intellisense should work without it*).
4. If the **[C++ extension][cpp ext]** is installed, disable its intellisense in
your workspace settings (*Clangd intellisense is better*)
```
"C_Cpp.intelliSenseEngine": "disabled"
```
5. In the VS Code Command Palette, run **CMake: Select Configure Preset**, then select the
**[preset][cmake presets]** you wish to build from the dropdown
* *The **Clang** presets may work best with the **Clangd** extension*
* *Intellisense won't work for generated files/types until you build libspark*
# Build Spark on Windows
### **Dependencies**
* **[CMake][cmake]** (version >= 3.23)
* **[Python][python]** (version >= 3.9)
* **[Visual Studio][visual studio]** (2022)
* **[Dotnet][dotnet]** (sdk version >= 7.0.0)
### **References**
* **[CMakePresets][cmake presets]**
* **[Visual Studio 17 2022 (CMake generator)][visual studio generator]**
* **[Python Virtual Environment][py venv]**
> *Run commands from the repo root dir unless otherwise noted*
1. Set up the **[Python virtual environment][py venv]**<br>
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
.venv\bin\activate.bat
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
> *Run commands in python virtual environment*
```
# Configure
cmake --preset spark
# Build Debug
cmake --build --preset spark-debug
dotnet build spark_client.sln --configuration Debug
# Build Release
cmake --build --preset spark-release
dotnet build spark_client.sln --configuration Release
```
# Build Sparkd on Linux
### **Dependencies**
* **[CMake][cmake]** (version >= 3.23)
* **[Ninja Build][ninja build]**
* **[Python][python]** (version >= 3.9)
* **[Docker][docker]**
### **References**
* **[CMakePresets][cmake presets]**
* **[Ninja (CMake generator)][ninja generator]**
* **[Python Virtual Environment][py venv]**
* **[Devcontainer](devcontainer)**
### **Prerequisites**
* Open repository in a VS Code [Devcontainer](../docker/sparkd/dev/README.md), or
create your own [docker container](../docker/sparkd/dev/README.md) in which to build
> *Run commands from the repo root dir unless otherwise noted*<br>
1. Set up the **[Python virtual environment][py venv]**
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
. .venv/bin/activate
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
> *Run commands in python virtual environment*
```
# Configure clang debug
cmake --preset sparkd-clang-debug
# Build clang debug
cmake --build --preset spark-clang-debug
# Configure gcc release
cmake --build --preset sparkd-gcc-release
# Build gcc release
cmake --build --preset sparkd-gcc-release
```
# Build Spark Api Server on Windows
### **Dependencies**
* **[CMake][cmake]** (version >= 3.23)
* **[Python][python]** (version >= 3.9)
* **[Visual Studio][visual studio]** (version)
* **[Dotnet][dotnet]** (sdk version >= 7.0.0)
### **References**
* **[CMakePresets][cmake presets]**
* **[Visual Studio 17 2022 (CMake generator)][visual studio generator]**
* **[Python Virtual Environment][py venv]**
> *Run commands from the repo root dir unless otherwise noted*
1. Set up the **[Python Virtual Environment][py venv]**
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
.venv\bin\activate.bat
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
> *Run in python virtual environment*
```
# Configure
cmake --preset spark-api-server-windows
# Build debug
cmake --build --preset spark-api-server-windows-debug
dotnet build Spark.Api.Server.sln --configuration Debug
# Build release
cmake --build --preset spark-api-server-windows-release
dotnet build Spark.Api.Server.sln --configuration Release
```
## Linux
### **Dependencies**
* **[CMake][cmake]** (version >= 3.23)
* **[Python][python]** (version >= 3.9)
* **[Dotnet][dotnet]** (sdk version >= 7.0.0)
### **References**
* **[CMakePresets][cmake presets]**
* **[Ninja Multi-Config (CMake generator)][ninja multi-config generator]**
* **[Python Virtual Environment][py venv]**
> *Run commands from the repo root dir unless otherwise noted*
1. Set up the **[Python Virtual Environment][py venv]**
```
# Create the virtual environment
python3 -m venv .venv
# Activate the virtual environment
. .venv/bin/activate
# Update pip
python -m pip install --upgrade pip
# Install packages
pip install -r requirements.txt
```
2. Build
> *Run in python virtual environment*
```
# Configure
cmake --preset spark-api-server-linux
# Build debug
cmake --build --preset spark-api-server-linux-debug
dotnet build Spark.Api.Server.sln --configuration Debug
# Build release
cmake --build --preset spark-api-server-linux-release
dotnet build Spark.Api.Server.sln --configuration Release
```
+66
View File
@@ -0,0 +1,66 @@
diff --git a/src/DataStreamSuite/SharedStreams/Business/MarketData/MDStream.cs b/src/DataStreamSuite/SharedStreams/Business/MarketData/MDStream.cs
index 643146112..e334c3aba 100644
--- a/src/DataStreamSuite/SharedStreams/Business/MarketData/MDStream.cs
+++ b/src/DataStreamSuite/SharedStreams/Business/MarketData/MDStream.cs
@@ -1,7 +1,9 @@
namespace BCG {
using BCG.Utilities.General;
+ using bts;
using bts.api;
+ using bts.api.core;
using bts.api.domain;
using bts.api.synthetic;
using bts.md;
@@ -14,6 +16,7 @@ namespace BCG {
using mbts.spark;
using mbts.ui;
+ using Spark.Api.MarketData;
using Spark.Core.Data;
using Spark.Core.Disposables;
using Spark.Core.Reactive;
@@ -39,6 +42,8 @@ namespace BCG {
new ColumnInfo("sec", 1, typeof(string))}, "md");
private BlueTable _rows;
+ readonly MarketDataClient mdClient;
+ IDisposable? mdSub;
public MDStream()
: this(String.Empty, ViewStreamDatabase.instance) {
@@ -49,14 +54,27 @@ namespace BCG {
_symbol = symbol;
_rows = new BlueTable(_schema);
_md_source = new MDSource(TimeSpan.FromSeconds(0.5));
+ mdClient = new(_md_source);
}
protected override void myOnFirstSubscriber() {
_vsd.addWorker(this);
_md_source.subscribe_securities().Subscribe(c => on_md(c));
+ Log.isnull(mdSub);
+ mdSub = mdClient.books().Subscribe(onBooks);
//base.myOnFirstSubscriber();
}
+ void onBooks(TableUpdate<BookTuple, uint> update) {
+ foreach (var book in update.added) {
+ bts.Log.Gen.info($"MDStream.on_md sec: {book.security}");
+ var sec = book.security;
+ IBlueRow r = new BlueRow(_schema, _id++, sec.ToString());
+ _rows.addRow(r);
+ _is_dirty = true;
+ }
+ }
+
protected override void myOnLastSubscriber() {
//base.myOnLastSubscriber();
_vsd.removeWorker(this);
@@ -82,4 +100,4 @@ namespace BCG {
}
}
}
-}
\ No newline at end of file
+}
+112
View File
@@ -0,0 +1,112 @@
diff --git a/src/client/spark/AW2/VolSurfaceExtensions.cs b/src/client/spark/AW2/VolSurfaceExtensions.cs
index 6279d82a2..c143902a7 100644
--- a/src/client/spark/AW2/VolSurfaceExtensions.cs
+++ b/src/client/spark/AW2/VolSurfaceExtensions.cs
@@ -162,7 +162,8 @@ namespace mbts.spark {
api_sec_exp.Exchange.to_venue(),
api_sec_exp.SecurityType.contract_case(),
api_sec_exp.Symbol,
- api_sec_exp.Expiration.date_time());
+ api_sec_exp.HasExpiration ?
+ api_sec_exp.Expiration.date_time() : SecurityExpiration.empty.expiration);
public static SecurityExpiration to_sec_exp(this Security sec) =>
to_sec_exp(new SecurityImmutable(sec));
diff --git a/src/client/spark/Analytics/Core/Settings/SecurityExpiration.cs b/src/client/spark/Analytics/Core/Settings/SecurityExpiration.cs
index bf9f44455..b2ac80561 100644
--- a/src/client/spark/Analytics/Core/Settings/SecurityExpiration.cs
+++ b/src/client/spark/Analytics/Core/Settings/SecurityExpiration.cs
@@ -3,6 +3,7 @@ namespace mbts {
using bts.api;
using bts.utils;
+ using mbts.spark;
using mbts.ui.utility;
using mbts.utils;
@@ -25,6 +26,9 @@ namespace mbts {
SecurityTuple.empty.security_name,
DateTime.MinValue);
+ public static bts.api.domain.SecurityExpirationImmutable empty_api_sec_expi =>
+ empty.to_api_sec_expi();
+
// for deserialization
SecurityExpiration() =>
security_tuple = SecurityTuple.empty;
diff --git a/src/client/spark/Analytics/SupportingData/AnalyticsExpirationParameters.cs b/src/client/spark/Analytics/SupportingData/AnalyticsExpirationParameters.cs
index f5e2a73d6..0ea7b34be 100644
--- a/src/client/spark/Analytics/SupportingData/AnalyticsExpirationParameters.cs
+++ b/src/client/spark/Analytics/SupportingData/AnalyticsExpirationParameters.cs
@@ -50,9 +50,7 @@ namespace mbts.analytics {
deliverable_security ??= SecurityExpiration.empty;
roll_schedule_expiration ??= SecurityExpiration.empty;
- this.driver = driver ?? new(new() {
- TimeWeightedInterpolated = new()
- });
+ this.driver = driver ?? _default_driver;
_deliverable = deliverable_security.to_api_sec_expi();
_roll_schedule = roll_schedule_expiration.to_api_sec_expi();
this.roll_target = roll_target;
@@ -63,10 +61,10 @@ namespace mbts.analytics {
}
public AnalyticsExpirationParameters(ExpirationParameterEntryImmutable db_i) {
- _security = db_i.SecurityExpiration;
- _deliverable = db_i.Deliverable;
- _roll_schedule = db_i.RollSchedule;
- driver = db_i.Driver;
+ _security = db_i.HasSecurityExpiration ? db_i.SecurityExpiration : _default_api_sec_expi;
+ _deliverable = db_i.HasDeliverable ? db_i.Deliverable : _default_api_sec_expi;
+ _roll_schedule = db_i.HasRollSchedule ? db_i.RollSchedule : _default_api_sec_expi;
+ driver = db_i.HasDriver ? db_i.Driver : _default_driver;
roll_target = db_i.RollTarget;
riskless_rate = db_i.RisklessRate;
settlement_price = db_i.SettlementPrice;
@@ -74,6 +72,12 @@ namespace mbts.analytics {
vega_beta = db_i.VegaBeta;
}
+ static ExpirationDriverImmutable _default_driver =>
+ new(new() { TimeWeightedInterpolated = new() });
+
+ static bts.api.domain.SecurityExpirationImmutable _default_api_sec_expi =>
+ SecurityExpiration.empty_api_sec_expi;
+
public SecurityExpiration security => _security.to_sec_exp();
public SecurityExpiration driver_security => driver.HasSecurity ?
driver.Security.to_sec_exp() : SecurityExpiration.empty;
diff --git a/src/client/spark/NMSheets/DataProviders/NMSheetSingleOptionMainDataSource.cs b/src/client/spark/NMSheets/DataProviders/NMSheetSingleOptionMainDataSource.cs
index 622121388..ec902f142 100644
--- a/src/client/spark/NMSheets/DataProviders/NMSheetSingleOptionMainDataSource.cs
+++ b/src/client/spark/NMSheets/DataProviders/NMSheetSingleOptionMainDataSource.cs
@@ -233,9 +233,18 @@ namespace BCG {
private IDictionary<DateTime, ATMData> _get_atm_data(ExpStrikeKeyedData<mbts.spark.TheoPoint> theo_data) {
NMSheetSettings sheet_settings = _threaded_bb.read_state(_in_bb_sheet_settings_tag) ?? new NMSheetSettings();
VolSurfaceNonVolInput vs_nvinp = _threaded_bb.read_state(_in_exp_param_tag);
- IDictionary<DateTime, double> option_exp_roll_data = vs_nvinp != null ?
- vs_nvinp.get_roll_map((exp) => exp.symbol == _nmsheet_symbol.option_name && exp.security_type == SecurityType.Option).ToDictionary(kv => kv.Key.expiration, kv => kv.Value) :
- new Dictionary<DateTime, double>();
+ var option_sym_exp_groups = vs_nvinp
+ ?.get_roll_map(exp =>
+ exp.symbol == _nmsheet_symbol.option_name &&
+ exp.security_type == SecurityType.Option)
+ ?.GroupBy(kv => kv.Key.expiration)
+ ?.ToDictionary(kv => kv.Key, kv => kv.ToList());
+ var option_exp_roll_data = vs_nvinp
+ ?.get_roll_map(exp =>
+ exp.symbol == _nmsheet_symbol.option_name &&
+ exp.security_type == SecurityType.Option)
+ ?.ToDictionary(kv => kv.Key.expiration, kv => kv.Value)
+ ?? new();
IDictionary<DateTime, ATMData> atm_data = OptionATMDataSource.compute_atm_data(_nmsheet_symbol.option_name, _get_onefive(), theo_data, option_exp_roll_data);
if (sheet_settings.setting_atm.select_atm_nearest_strike_only)
foreach (ATMData exp_atm_data in atm_data.Values)
@@ -306,4 +315,4 @@ namespace BCG {
}
#endregion
}
-}
\ No newline at end of file
+}
+45
View File
@@ -0,0 +1,45 @@
/* global use, db */
// MongoDB Playground
// To disable this template go to Settings | MongoDB | Use Default Template For Playground.
// Make sure you are connected to enable completions and to be able to run a playground.
// Use Ctrl+Space inside a snippet or a string literal to trigger completions.
// The result of the last command run in a playground is shown on the results panel.
// By default the first 20 documents will be returned with a cursor.
// Use 'console.log()' to print to the debug output.
// For more documentation on playgrounds please refer to
// https://www.mongodb.com/docs/mongodb-vscode/playgrounds/
// Select the database to use.
use('mongodbVSCodePlaygroundDB');
// Insert a few documents into the sales collection.
db.getCollection('sales').insertMany([
{ 'item': 'abc', 'price': 10, 'quantity': 2, 'date': new Date('2014-03-01T08:00:00Z') },
{ 'item': 'jkl', 'price': 20, 'quantity': 1, 'date': new Date('2014-03-01T09:00:00Z') },
{ 'item': 'xyz', 'price': 5, 'quantity': 10, 'date': new Date('2014-03-15T09:00:00Z') },
{ 'item': 'xyz', 'price': 5, 'quantity': 20, 'date': new Date('2014-04-04T11:21:39.736Z') },
{ 'item': 'abc', 'price': 10, 'quantity': 10, 'date': new Date('2014-04-04T21:23:13.331Z') },
{ 'item': 'def', 'price': 7.5, 'quantity': 5, 'date': new Date('2015-06-04T05:08:13Z') },
{ 'item': 'def', 'price': 7.5, 'quantity': 10, 'date': new Date('2015-09-10T08:43:00Z') },
{ 'item': 'abc', 'price': 10, 'quantity': 5, 'date': new Date('2016-02-06T20:20:13Z') },
]);
// Run a find command to view items sold on April 4th, 2014.
const salesOnApril4th = db.getCollection('sales').find({
date: { $gte: new Date('2014-04-04'), $lt: new Date('2014-04-05') }
}).count();
// Print a message to the output window.
console.log(`${salesOnApril4th} sales occurred in 2014.`);
// Here we run an aggregation and open a cursor to the results.
// Use '.toArray()' to exhaust the cursor to return the whole result set.
// You can use '.hasNext()/.next()' to iterate through the cursor page by page.
db.getCollection('sales').aggregate([
// Find all of the sales that occurred in 2014.
{ $match: { date: { $gte: new Date('2014-01-01'), $lt: new Date('2015-01-01') } } },
// Group the total sales for each product.
{ $group: { _id: '$item', totalSaleAmount: { $sum: { $multiply: ['$price', '$quantity'] } } } }
]);
+6 -2
View File
@@ -1,18 +1,22 @@
astroid==2.7.3
autopep8==1.5.7
cffi==1.14.6
certifi==2023.5.7
charset-normalizer==3.1.0
colorama==0.4.4
idna==3.4
isort==5.9.3
lazy-object-proxy==1.6.0
mccabe==0.6.1
platformdirs==2.3.0
protobuf==3.19.1
protobuf==4.21.12
pybars3==0.9.7
pycodestyle==2.7.0
pycparser==2.20
pylint==2.10.2
PyMeta3==0.5.1
requests==2.31.0
termcolor==1.1.0
toml==0.10.2
urllib3==2.0.3
wrapt==1.12.1
yapf==0.31.0
-41
View File
@@ -1,41 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sparkd", "src\server\sparkd\sparkd.vcxproj", "{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libspark", "build\src\lib\libspark.vcxproj", "{502FD050-679A-3B50-B438-098500700919}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
MinSizeRel|x64 = MinSizeRel|x64
Release|x64 = Release|x64
RelWithDebInfo|x64 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.Debug|x64.ActiveCfg = Debug|x64
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.Debug|x64.Build.0 = Debug|x64
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.MinSizeRel|x64.ActiveCfg = Release|x64
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.MinSizeRel|x64.Build.0 = Release|x64
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.Release|x64.ActiveCfg = Release|x64
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.Release|x64.Build.0 = Release|x64
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{BBBAFD38-312D-4A8D-9AF0-F2BDEE72CE6F}.RelWithDebInfo|x64.Build.0 = Release|x64
{502FD050-679A-3B50-B438-098500700919}.Debug|x64.ActiveCfg = Debug|x64
{502FD050-679A-3B50-B438-098500700919}.Debug|x64.Build.0 = Debug|x64
{502FD050-679A-3B50-B438-098500700919}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{502FD050-679A-3B50-B438-098500700919}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{502FD050-679A-3B50-B438-098500700919}.Release|x64.ActiveCfg = Release|x64
{502FD050-679A-3B50-B438-098500700919}.Release|x64.Build.0 = Release|x64
{502FD050-679A-3B50-B438-098500700919}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{502FD050-679A-3B50-B438-098500700919}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6A7249D7-B40C-4656-9347-60072D0B8FDB}
EndGlobalSection
EndGlobal
+30
View File
@@ -0,0 +1,30 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIgmHCnJpc1awCAggA
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECPGPVlg9BOO1BIIEyHTdfD5zGKyf
hHVm4So+G8TtIQvL+xu0oLNKQR/DVo3wo3iUD70h7oXQnLJ4CL5qo9nR75u2UghL
mg6xGFbmvpIX/2LAHsS3+MzmOYWKAr0sjmFgJ0YJ/Km6zL88wpk8Gxf3KW3PTZta
+STA1OVPzggSxbHNV16kD9mVUwzOGxD6+zmkRBrvVr3z7/Y8DO8102QrT13U7wy3
RWWo9cNFSS4UG1yeOy0IGRzvfPVf8si6xO2GXKJZX1W3pfpUihEVDynz9I7pkw0/
NF9CVROOgY351d0Vs7is+K9q1etpAHTRJl5phpQUXX6DTXlkjWInAXYcs+4z/kEK
icUa9fijxvz+rx67WkEn4TmaBCIkPVJukeJFh2NHKEj9nK88/okjDExes9TDC4HC
riGoT7honGjkmeIQd0EZo3YXzCCRcr5hCjx3z5CQThLY0MT3avNqYLs6qwaEL4ho
Mnkiiwm/d8n5AGpqm1dI8hmJMhlQzL5a6fpcgst6bqVc7MMRrTNnY/k8ptoXyHWI
XXkcf1SWBxwK5u14AoH5u40LORz0Shn9PKL05EeAqK5eh9TX+HmxCE7pES4uceRJ
nBYjPp8q/NkhqHhMlVZgNcZoY3edPY4We5nYKpW4uLFl9DPckFKlaQpN+dVcSY0I
vIsRaKXeju3YpzehRE80ztE4f8ZO8nyuGScx1PV0mYlXsjMJpAkV2J7Y3BVdFRsk
bvQ2zfhgX5LQeC9MU0jn5cZbBO67eFxmEvtZKRt0ooZSNR748NqbfO2wHOuxfLOe
UeZfKGvpJhHqH+nZQiEKIldf7A9ORQeVr/yhR+shv91GJtUE89cm725ODFe5NiHw
FWVgyBFuB4DN/XVvD8oS7S+Io/q+YAfbDzYqqYjlCuoQcrEfhkcWJOKZ7nEXqEdN
W/Ly6HAl2QddVK8xj93IGLYhzEZSU8ldw7KhRwXE2jAe9cB+tygOWygxfVpt6d3i
q0xBLvlUVWC2aviOtQ+xvNb54JPPRTnOZ2RsOUkTPDrTEFeEm0O0lbPI1PSIMlGH
BSQukR+n0vRfmRRs/OXipe2zJEDy6+BJ44uV+Pz5aARH4arvnfWnRKlx5+b58HEd
Six4y+Sz2i5k6MwRCQyuPTBJHpp6zvwFCX1doPrcCN6Q0GjtDWGklPyofmuLSM3d
8sHciqGLfv6+hSH/yY/SbyyU2MYx5WJoREYIfQ1M/V6ycppmIb7QDXrQ6nVd33FC
73OpKaB/q1tIgdImUT7J0PeM6EmjKC3g6y0iGp9adAF2BMe19rOQjrn9lHMbFb9w
/4uZDTLPmYZyONmMFnL47PoD3MUlJFvDPN//9g1DTk3lMLHETNzv7Lh6vR2h5Otl
x9SnakCahQDcLYvxdKNSKHfClwMuS3gjpoT45Qki0APH+dYwGYNXDLj41t61fYkl
v7IoGoHJ3Ym8ySWtS5MMt4kdb7eiVAzGla5TEa1RqOtU31A6W3GKSOzlY7znaBoi
Q/aGtZq/AhU4DOba5pT/ddB442fnG/8i2un6oSAthtK6VvHx4ebBDxTgV8Fp62le
dCLw93+lppVS8ChRH2MQDS2Mr/khQo5f+BybnY6zVBRJh7rvQ7g4U0qBzpoaj+nD
IiX/FNTzdAYjmFa+iHB2OQ==
-----END ENCRYPTED PRIVATE KEY-----
+9
View File
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvvtV/IP1l/F85ME8N8H+
8TCBOB68Lxd7sdR0geJGssLBq5F22IIlVKylNxiQV3TE6/hmL9dmr8FuUMrjPCal
vma0axyAdyCMjFH3U0bYzzxnxSWuj5VJIgaZKOVQuX/3Hb+l4RZi7VWZgQFvEJ+F
y66S2wDu4ey71Mt0yxkMsl5WMZBL3M1z+bt3pKzmBoyIMVLDcV1k1Yr2wspIRriZ
95er3JWofK1P9s8B3OoqypEopLRW5hJaZN8YRpFNq5VwRUSj83KVobBAQTWDdOA5
zOkixPVklZFaNyR06iT0gcgZUUM2bjyfQJGQ4GBCZpZb8KPPgtP+WhghoWby9OLv
KQIDAQAB
-----END PUBLIC KEY-----
+2 -15
View File
@@ -1,21 +1,16 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32922.545
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api", "src\client\spark_api\spark_api.csproj", "{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libspark", "build\src\lib\libspark.vcxproj", "{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spark", "src\client\spark\Spark.csproj", "{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sparkcmd", "src\client\sparkcmd\sparkcmd.csproj", "{387566C6-C6F6-412C-A30C-9855BBCB4816}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spark.Console", "src\client\Spark.Console\Spark.Console.csproj", "{387566C6-C6F6-412C-A30C-9855BBCB4816}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_core", "src\client\spark_core\spark_core.csproj", "{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_sdk", "src\client\spark_sdk\spark_sdk.csproj", "{6963C314-83C4-4667-B0D0-C2F7AE208C29}"
ProjectSection(ProjectDependencies) = postProject
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25} = {FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_test", "src\client\spark_test\spark_test.csproj", "{ECD78CC5-138F-4809-A764-2358C2AC2E82}"
EndProject
@@ -39,14 +34,6 @@ Global
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x64.Build.0 = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.Build.0 = Release|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Debug|x64.ActiveCfg = Debug|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Debug|x64.Build.0 = Debug|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Release|x64.ActiveCfg = Release|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Release|x64.Build.0 = Release|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.ActiveCfg = Debug|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.Build.0 = Debug|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|x64.ActiveCfg = Release|x64
@@ -0,0 +1,37 @@
namespace Bts.ArithmeticExpressions;
using System.Numerics;
class AdditiveInverse : IArithmeticExpression<double> {
readonly IArithmeticExpression expression;
public AdditiveInverse(IArithmeticExpression expression) =>
this.expression = expression;
public static AdditiveInverse<T> Create<T>(IArithmeticExpression<T> expression)
where T : INumber<T> =>
new(expression);
public double Evaluate(IDictionary<string, object?> env) =>
-evaluateArg(expression, nameof(expression), env);
static double evaluateArg(
IArithmeticExpression expr, string name, IDictionary<string, object?> env) {
var obj = expr.Evaluate(env);
return ConvertUtils.try_convert(expr.Evaluate(env), out double dbl) ? dbl :
throw new Exception(
$"Invalid AdditiveInverse. {name} is of type {obj?.GetType()} " +
$"(expected {typeof(double)})");
}
}
class AdditiveInverse<T> : IArithmeticExpression<T>
where T : INumber<T> {
readonly IArithmeticExpression<T> expression;
public AdditiveInverse(IArithmeticExpression<T> expression) =>
this.expression = expression;
public T Evaluate(IDictionary<string, object?> env) =>
-expression.Evaluate(env);
}
@@ -0,0 +1,45 @@
namespace Bts.ArithmeticExpressions;
using System.Numerics;
public static class ArithmeticExpressionExtensions {
public static IArithmeticExpression<TResult> Add<TLeft, TRight, TResult>(
this IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right)
where TLeft :
INumber<TLeft>,
IAdditionOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> =>
new Sum<TLeft, TRight, TResult>(left, right);
public static IArithmeticExpression<TResult> Subtract<TLeft, TRight, TResult>(
this IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right)
where TLeft :
INumber<TLeft>,
ISubtractionOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> =>
new Difference<TLeft, TRight, TResult>(left, right);
public static IArithmeticExpression<TResult> Multiply<TLeft, TRight, TResult>(
this IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right)
where TLeft :
INumber<TLeft>,
IMultiplyOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> =>
new Product<TLeft, TRight, TResult>(left, right);
public static IArithmeticExpression<TResult> Divide<TLeft, TRight, TResult>(
this IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right)
where TLeft :
INumber<TLeft>,
IDivisionOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> =>
new Quotient<TLeft, TRight, TResult>(left, right);
public static IArithmeticExpression<T> Negate<T>(this IArithmeticExpression<T> expression)
where T : INumber<T> =>
new AdditiveInverse<T>(expression);
}
@@ -0,0 +1,99 @@
%namespace Bts.ArithmeticExpressions
%partial
%visibility internal
%tokentype Token
%parsertype ArithmeticExpressionParserImpl
%union {
public int Integer;
public double Real;
public string Identifier;
public DateTime DateTime;
public ImmutableList<IArithmeticExpression> Arguments;
public ImmutableList<Assignment> Assignments;
public IArithmeticExpression Argument;
public Assignment Assignment;
public ArithmeticProgram Program;
}
/* Constants */
%token INTEGER_CONSTANT REAL_CONSTANT
/* Arithmetic Operators */
%token ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUALS
/* Syntax */
%token PARENTHESIS_OPEN, PARENTHESIS_CLOSE, COMMA, IDENTIFIER
%left ADD SUBTRACT
%left MULTIPLY DIVIDE
%nonassoc EQUALS
%type <Argument> Argument
%type <Arguments> Arguments
%type <Assignment> Assignment
%type <Assignments> Assignments
%type <Program> Program
%%
Program :
Assignments {
$$ = new($1);
}
;
Assignments :
Assignment {
$$ = ImmutableList<Assignment>.Empty.Add($1);
}
| Assignments Assignment {
$$ = $1.Add($2);
}
;
Assignment :
IDENTIFIER EQUALS Argument {
$$ = new($1.Identifier, $3);
}
;
Argument :
IDENTIFIER PARENTHESIS_OPEN Arguments PARENTHESIS_CLOSE {
$$ = new Function($1.Identifier, $3);
}
| INTEGER_CONSTANT {
$$ = new IntegerConstant($1.Integer);
}
| REAL_CONSTANT {
$$ = new RealConstant($1.Real);
}
| IDENTIFIER {
$$ = new Variable($1.Identifier);
}
| SUBTRACT Argument {
$$ = $2.Negate();
}
| PARENTHESIS_OPEN Argument PARENTHESIS_CLOSE {
$$ = $2;
}
| Argument MULTIPLY Argument {
$$ = $1.Multiply($3);
}
| Argument DIVIDE Argument {
$$ = $1.Divide($3);
}
| Argument ADD Argument {
$$ = $1.Add($3);
}
| Argument SUBTRACT Argument {
$$ = $1.Subtract($3);
}
;
Arguments :
Argument {
$$ = ImmutableList<IArithmeticExpression>.Empty.Add($1);
}
| Arguments COMMA Argument {
$$ = $1.Add($3);
}
;
@@ -0,0 +1,19 @@
namespace Bts.ArithmeticExpressions;
using System.Text;
partial class ArithmeticExpressionParserImpl {
public ArithmeticExpressionParserImpl() : base(null) { }
public ValueType Parse(Stream stream) {
Scanner = new ArithmeticExpressionScanner(stream);
Parse();
return CurrentSemanticValue;
}
public ValueType Parse(string str) {
var inputBuffer = Encoding.Default.GetBytes(str);
using var stream = new MemoryStream(inputBuffer);
return Parse(stream);
}
}
@@ -0,0 +1,11 @@
namespace Bts.ArithmeticExpressions;
using System;
partial class ArithmeticExpressionScanner {
public override void yyerror(string format, params object[] args) {
base.yyerror(format, args);
Console.WriteLine(format, args);
Console.WriteLine();
}
}
@@ -0,0 +1,70 @@
%namespace Bts.ArithmeticExpressions
%scannertype ArithmeticExpressionScanner
%visibility internal
%tokentype Token
%option stack, minimize, parser, verbose, persistbuffer, noembedbuffers
Letter [a-zA-Z]
Identifier {Letter}({Letter}*[0-9]*_*)*
IntegerConstant -?[0-9]+
RealConstant -?[0-9]+\.[0-9]+
ParenthesisOpen \(
ParenthesisClose \)
Add \+
Subtract \-
Multiply \*
Divide /
Equals =
Comma ,
%%
{IntegerConstant} {
yylval.Integer = int.Parse(yytext);
return (int)Token.INTEGER_CONSTANT;
}
{RealConstant} {
yylval.Real = double.Parse(yytext);
return (int)Token.REAL_CONSTANT;
}
{Identifier} {
yylval.Identifier = yytext;
return (int)Token.IDENTIFIER;
}
{ParenthesisOpen} {
return (int)Token.PARENTHESIS_OPEN;
}
{ParenthesisClose} {
return (int)Token.PARENTHESIS_CLOSE;
}
{Add} {
return (int)Token.ADD;
}
{Subtract} {
return (int)Token.SUBTRACT;
}
{Multiply} {
return (int)Token.MULTIPLY;
}
{Divide} {
return (int)Token.DIVIDE;
}
{Equals} {
return (int)Token.EQUALS;
}
{Comma} {
return (int)Token.COMMA;
}
%%
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.24.3" />
<PackageReference Include="YaccLexTools" Version="1.2.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ExpressionCore\ExpressionCore.csproj" />
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
</ItemGroup>
<ItemGroup Label="ArithmeticExpression">
<Scanner Include="ArithmeticExpressionTokens.lex" />
<Parser Include="ArithmeticExpressionGrammar.y" />
</ItemGroup>
</Project>
@@ -0,0 +1,21 @@
namespace Bts.ArithmeticExpressions;
using System.Collections.Immutable;
class ArithmeticProgram : IArithmeticProgram {
readonly ImmutableList<Assignment>? assignments;
public ArithmeticProgram(Assignment assignment) =>
assignments = ImmutableList<Assignment>.Empty.Add(assignment);
public ArithmeticProgram(ImmutableList<Assignment> assignments) =>
this.assignments = assignments;
IEnumerable<string> IArithmeticProgram.OutputIdentifiers =>
assignments.empty_if_null()
.Select(a => a.Identifier ?? throw new Exception("Identifier string is null"))
.Distinct();
IDictionary<string, object?> IArithmeticProgram.Evaluate(IDictionary<string, object?> env) =>
assignments.empty_if_null().Aggregate(env, (e, a) => a.Evaluate(e));
}
@@ -0,0 +1,16 @@
namespace Bts.ArithmeticExpressions;
using Bts.ExpressionCore;
public static class ArithmeticProgramParser {
public static IArithmeticProgram Parse(Stream expression) =>
new Parser().Parse(expression);
public static IArithmeticProgram Parse(string expression) =>
new Parser().Parse(expression);
class Parser : IParser<ArithmeticProgram> {
public ArithmeticProgram Parse(Stream expression) =>
new ArithmeticExpressionParserImpl().Parse(expression).Program;
}
}
@@ -0,0 +1,24 @@
namespace Bts.ArithmeticExpressions;
public class Assignment {
public Assignment(string? identifier, IArithmeticExpression? value) {
Identifier = identifier ?? throw new ArgumentNullException(nameof(identifier));
Value = value ?? throw new ArgumentNullException(nameof(identifier));
}
public string? Identifier { get; }
public IArithmeticExpression? Value { get; }
public IDictionary<string, object?> Evaluate(IDictionary<string, object?> env) {
if (Identifier is null) {
throw new InvalidOperationException("Identifier is null");
}
if (Value is null) {
throw new InvalidOperationException($"Value is null (Identifier '{Identifier}')");
}
env[Identifier] = Value.Evaluate(env) ?? throw new Exception(
$"{nameof(Assignment)}.{nameof(Value)} (of type '{Value.GetType()}') " +
$"evaluated to null (Identifier '{Identifier}')");
return env;
}
}
@@ -0,0 +1,45 @@
namespace Bts.ArithmeticExpressions;
using System.Numerics;
public class Difference : IArithmeticExpression<double> {
readonly IArithmeticExpression lhs;
readonly IArithmeticExpression rhs;
public Difference(IArithmeticExpression lhs, IArithmeticExpression rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
public static Difference<T, T, T> Create<T>(
IArithmeticExpression<T> left, IArithmeticExpression<T> right)
where T : INumber<T>, ISubtractionOperators<T, T, T> =>
new(left, right);
public double Evaluate(IDictionary<string, object?> env) =>
evaluateArg(lhs, nameof(lhs), env) - evaluateArg(rhs, nameof(rhs), env);
static double evaluateArg(
IArithmeticExpression expr, string name, IDictionary<string, object?> env) {
var obj = expr.Evaluate(env);
return ConvertUtils.try_convert(expr.Evaluate(env), out double dbl) ? dbl :
throw new Exception(
$"Invalid Difference. {name} is of type {obj?.GetType()} (expected {typeof(double)})");
}
}
public class Difference<TLeft, TRight, TResult> : IArithmeticExpression<TResult>
where TLeft : INumber<TLeft>, ISubtractionOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> {
readonly IArithmeticExpression<TLeft> left;
readonly IArithmeticExpression<TRight> right;
public Difference(IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right) {
this.left = left;
this.right = right;
}
public TResult Evaluate(IDictionary<string, object?> env) =>
left.Evaluate(env) - right.Evaluate(env);
}
@@ -0,0 +1,208 @@
namespace Bts.ArithmeticExpressions;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
class EvaluationEnvironment : IDictionary<string, object?>, IReadOnlyDictionary<string, object?> {
IDictionary<string, object?> outerEnv;
IDictionary<string, object?> innerEnv = new Dictionary<string, object?>();
int? count;
public EvaluationEnvironment(IDictionary<string, object?> initial) =>
outerEnv = initial;
public object? this[string key] {
get {
if (innerEnv.TryGetValue(key, out var rv)) {
return rv;
}
if (outerEnv.TryGetValue(key, out rv)) {
return rv;
}
throw new Exception($"Undefined identifier '{key}'");
}
set {
if (count.HasValue && !ContainsKey(key)) {
count = count.Value + 1;
innerEnv.Add(key, value);
return;
}
innerEnv[key] = value;
}
}
public IDictionary<string, object?> Result =>
innerEnv;
public ICollection<string> Keys =>
new KeyCollection(outerEnv, innerEnv);
public ICollection<object?> Values =>
new ValueCollection(outerEnv, innerEnv);
public int Count =>
count ??= countKeys(outerEnv, innerEnv);
public bool IsReadOnly => throw new NotImplementedException();
public bool ContainsKey(string key) =>
innerEnv.ContainsKey(key) || outerEnv.ContainsKey(key);
public bool TryGetValue(string key, [MaybeNullWhen(false)] out object? value) =>
innerEnv.TryGetValue(key, out value) || outerEnv.TryGetValue(key, out value);
public IEnumerator<KeyValuePair<string, object?>> GetEnumerator() {
foreach (var kv in innerEnv) {
yield return kv;
}
foreach (var kv in outerEnv.Except()) {
if (!innerEnv.ContainsKey(kv.Key)) {
yield return kv;
}
}
}
public void Add(string key, object? value) {
if (ContainsKey(key)) {
throw new ArgumentException(
$"An element with the same key ({key}) already exists", nameof(key));
}
innerEnv.Add(key, value);
}
public void Add(KeyValuePair<string, object?> item) =>
Add(item.Key, item.Value);
public void Clear() =>
throw new NotSupportedException();
public bool Contains(KeyValuePair<string, object?> item) =>
TryGetValue(item.Key, out var v) && Equals(v, item.Value);
public void CopyTo(KeyValuePair<string, object?>[] array, int arrayIndex) {
foreach (var kv in innerEnv) {
array[arrayIndex++] = kv;
}
foreach (var kv in outerEnv) {
if (!innerEnv.ContainsKey(kv.Key)) {
array[arrayIndex++] = kv;
}
}
}
public bool Remove(string key) =>
throw new NotSupportedException();
public bool Remove(KeyValuePair<string, object?> item) =>
throw new NotSupportedException();
static int countKeys(IDictionary<string, object?> d1, IDictionary<string, object?> d2) =>
d1.Count > d2.Count ?
d1.Count + d2.Keys.WhereNot(d1.ContainsKey).Count() :
d2.Count + d1.Keys.WhereNot(d2.ContainsKey).Count();
IEnumerable<string> IReadOnlyDictionary<string, object?>.Keys => Keys;
IEnumerable<object?> IReadOnlyDictionary<string, object?>.Values => Values;
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
class KeyCollection : ICollection<string> {
readonly IDictionary<string, object?> outerEnv;
readonly IDictionary<string, object?> innerEnv;
public KeyCollection(
IDictionary<string, object?> outerEnv, IDictionary<string, object?> innerEnv) {
this.outerEnv = outerEnv;
this.innerEnv = innerEnv;
}
public int Count =>
countKeys(outerEnv, innerEnv);
public bool IsReadOnly => true;
public void Add(string item) =>
throw new NotSupportedException();
public void Clear() =>
throw new NotSupportedException();
public bool Contains(string item) =>
innerEnv.ContainsKey(item) || outerEnv.ContainsKey(item);
public void CopyTo(string[] array, int arrayIndex) {
foreach (var k in this) {
array[arrayIndex++] = k;
}
}
public IEnumerator<string> GetEnumerator() {
foreach (var k in innerEnv.Keys) {
yield return k;
}
foreach (var k in outerEnv.Keys) {
if (!innerEnv.ContainsKey(k)) {
yield return k;
}
}
}
public bool Remove(string item) =>
throw new NotSupportedException();
IEnumerator IEnumerable.GetEnumerator() =>
GetEnumerator();
}
class ValueCollection : ICollection<object?> {
readonly IDictionary<string, object?> outerEnv;
readonly IDictionary<string, object?> innerEnv;
public ValueCollection(
IDictionary<string, object?> outerEnv, IDictionary<string, object?> innerEnv) {
this.outerEnv = outerEnv;
this.innerEnv = innerEnv;
}
public int Count =>
// Not a typo (obv, numValues == numKeys)
countKeys(outerEnv, innerEnv);
public bool IsReadOnly => true;
public void Add(object? item) =>
throw new NotSupportedException();
public void Clear() =>
throw new NotSupportedException();
public bool Contains(object? item) =>
innerEnv.Values.Contains(item) ||
outerEnv
.Where(kv => !innerEnv.ContainsKey(kv.Key))
.Select(kv => kv.Value)
.Contains(item);
public void CopyTo(object?[] array, int arrayIndex) {
foreach (var k in this) {
array[arrayIndex++] = k;
}
}
public IEnumerator<object?> GetEnumerator() {
foreach (var k in innerEnv.Values) {
yield return k;
}
foreach (var kv in outerEnv) {
if (!innerEnv.ContainsKey(kv.Key)) {
yield return kv.Value;
}
}
}
public bool Remove(object? item) =>
throw new NotSupportedException();
IEnumerator IEnumerable.GetEnumerator() =>
GetEnumerator();
}
}
@@ -0,0 +1,34 @@
namespace Bts.ArithmeticExpressions;
using Spark.Core;
using System.Collections.Immutable;
using System.Data;
public class Function : IArithmeticExpression {
public Function(string? identifier, ImmutableList<IArithmeticExpression>? arguments) {
Identifier = identifier;
Arguments = arguments;
}
public string? Identifier { get; }
public ImmutableList<IArithmeticExpression>? Arguments { get; }
public object? Evaluate(IDictionary<string, object?> env) {
if (Identifier is null) {
throw new InvalidOperationException("Identifier is null");
}
if (Arguments is null) {
throw new InvalidOperationException("Arguments is null");
}
if (Identifier == "ifNull") {
throw new NotImplementedException("'ifNull' function not yet implemented");
}
var argVals = Arguments.Select(e => e.Evaluate(env)).ToArray();
var argTypes = Array.ConvertAll(argVals, v => v?.GetType() ?? typeof(object));
var method = typeof(Math).GetMethod(Identifier, argTypes) ??
throw new EvaluateException(
$"Failed to find method '{Identifier}({", ".join(argTypes)})' in {typeof(Math)}");
return method.Invoke(null, argVals);
}
}
@@ -0,0 +1,720 @@
// ==============================================================
// <auto-generated>
// This code automatically produced from an embedded resource.
// Do not edit this file, or it will become incompatible with
// the specification from which it was generated.
// </auto-generated>
// ==============================================================
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using System.Globalization;
namespace QUT.GplexBuffers
{
// Code copied from GPLEX embedded resource
[Serializable]
internal class BufferException : Exception
{
public BufferException() { }
public BufferException(string message) : base(message) { }
public BufferException(string message, Exception innerException)
: base(message, innerException) { }
protected BufferException(SerializationInfo info, StreamingContext context)
: base(info, context) { }
}
internal abstract class ScanBuff
{
private string fileNm;
public const int EndOfFile = -1;
public const int UnicodeReplacementChar = 0xFFFD;
public bool IsFile { get { return (fileNm != null); } }
public string FileName { get { return fileNm; } set { fileNm = value; } }
public abstract int Pos { get; set; }
public abstract int Read();
public virtual void Mark() { }
public abstract string GetString(int begin, int limit);
public static ScanBuff GetBuffer(string source)
{
return new StringBuffer(source);
}
public static ScanBuff GetBuffer(IList<string> source)
{
return new LineBuffer(source);
}
#if (!NOFILES)
public static ScanBuff GetBuffer(Stream source)
{
return new BuildBuffer(source);
}
#if (!BYTEMODE)
public static ScanBuff GetBuffer(Stream source, int fallbackCodePage)
{
return new BuildBuffer(source, fallbackCodePage);
}
#endif // !BYTEMODE
#endif // !NOFILES
}
#region Buffer classes
// ==============================================================
// ===== Definitions for various ScanBuff derived classes ====
// ==============================================================
// =============== String input ================
// ==============================================================
/// <summary>
/// This class reads characters from a single string as
/// required, for example, by Visual Studio language services
/// </summary>
sealed class StringBuffer : ScanBuff
{
string str; // input buffer
int bPos; // current position in buffer
int sLen;
public StringBuffer(string source)
{
this.str = source;
this.sLen = source.Length;
this.FileName = null;
}
public override int Read()
{
if (bPos < sLen) return str[bPos++];
else if (bPos == sLen) { bPos++; return '\n'; } // one strike, see new line
else { bPos++; return EndOfFile; } // two strikes and you're out!
}
public override string GetString(int begin, int limit)
{
// "limit" can be greater than sLen with the BABEL
// option set. Read returns a "virtual" EOL if
// an attempt is made to read past the end of the
// string buffer. Without the guard any attempt
// to fetch yytext for a token that includes the
// EOL will throw an index exception.
if (limit > sLen) limit = sLen;
if (limit <= begin) return "";
else return str.Substring(begin, limit - begin);
}
public override int Pos
{
get { return bPos; }
set { bPos = value; }
}
public override string ToString() { return "StringBuffer"; }
}
// ==============================================================
// The LineBuff class contributed by Nigel Horspool,
// nigelh@cs.uvic.cs
// ==============================================================
sealed class LineBuffer : ScanBuff
{
IList<string> line; // list of source lines from a file
int numLines; // number of strings in line list
string curLine; // current line in that list
int cLine; // index of current line in the list
int curLen; // length of current line
int curLineStart; // position of line start in whole file
int curLineEnd; // position of line end in whole file
int maxPos; // max position ever visited in whole file
int cPos; // ordinal number of code in source
// Constructed from a list of strings, one per source line.
// The lines have had trailing '\n' characters removed.
public LineBuffer(IList<string> lineList)
{
line = lineList;
numLines = line.Count;
cPos = curLineStart = 0;
curLine = (numLines > 0 ? line[0] : "");
maxPos = curLineEnd = curLen = curLine.Length;
cLine = 1;
FileName = null;
}
public override int Read()
{
if (cPos < curLineEnd)
return curLine[cPos++ - curLineStart];
if (cPos++ == curLineEnd)
return '\n';
if (cLine >= numLines)
return EndOfFile;
curLine = line[cLine];
curLen = curLine.Length;
curLineStart = curLineEnd + 1;
curLineEnd = curLineStart + curLen;
if (curLineEnd > maxPos)
maxPos = curLineEnd;
cLine++;
return curLen > 0 ? curLine[0] : '\n';
}
// To speed up searches for the line containing a position
private int cachedPosition;
private int cachedIxdex;
private int cachedLineStart;
// Given a position pos within the entire source, the results are
// ix -- the index of the containing line
// lstart -- the position of the first character on that line
private void findIndex(int pos, out int ix, out int lstart)
{
if (pos >= cachedPosition)
{
ix = cachedIxdex; lstart = cachedLineStart;
}
else
{
ix = lstart = 0;
}
while (ix < numLines)
{
int len = line[ix].Length + 1;
if (pos < lstart + len) break;
lstart += len;
ix++;
}
cachedPosition = pos;
cachedIxdex = ix;
cachedLineStart = lstart;
}
public override string GetString(int begin, int limit)
{
if (begin >= maxPos || limit <= begin) return "";
int endIx, begIx, endLineStart, begLineStart;
findIndex(begin, out begIx, out begLineStart);
int begCol = begin - begLineStart;
findIndex(limit, out endIx, out endLineStart);
int endCol = limit - endLineStart;
string s = line[begIx];
if (begIx == endIx)
{
// the usual case, substring all on one line
return (endCol <= s.Length) ?
s.Substring(begCol, endCol - begCol)
: s.Substring(begCol) + "\n";
}
// the string spans multiple lines, yuk!
StringBuilder sb = new StringBuilder();
if (begCol < s.Length)
sb.Append(s.Substring(begCol));
for (; ; )
{
sb.Append("\n");
s = line[++begIx];
if (begIx >= endIx) break;
sb.Append(s);
}
if (endCol <= s.Length)
{
sb.Append(s.Substring(0, endCol));
}
else
{
sb.Append(s);
sb.Append("\n");
}
return sb.ToString();
}
public override int Pos
{
get { return cPos; }
set
{
cPos = value;
findIndex(cPos, out cLine, out curLineStart);
// cLine should be the *next* line after curLine.
curLine = (cLine < numLines ? line[cLine++] : "");
curLineEnd = curLineStart + curLine.Length;
}
}
public override string ToString() { return "LineBuffer"; }
}
#if (!NOFILES)
// ==============================================================
// ===== class BuildBuff : for unicode text files ========
// ==============================================================
class BuildBuffer : ScanBuff
{
// Double buffer for char stream.
class BufferElement
{
StringBuilder bldr = new StringBuilder();
StringBuilder next = new StringBuilder();
int minIx;
int maxIx;
int brkIx;
bool appendToNext;
internal BufferElement() { }
internal int MaxIndex { get { return maxIx; } }
// internal int MinIndex { get { return minIx; } }
internal char this[int index]
{
get
{
if (index < minIx || index >= maxIx)
throw new BufferException("Index was outside data buffer");
else if (index < brkIx)
return bldr[index - minIx];
else
return next[index - brkIx];
}
}
internal void Append(char[] block, int count)
{
maxIx += count;
if (appendToNext)
this.next.Append(block, 0, count);
else
{
this.bldr.Append(block, 0, count);
brkIx = maxIx;
appendToNext = true;
}
}
internal string GetString(int start, int limit)
{
if (limit <= start)
return "";
if (start >= minIx && limit <= maxIx)
if (limit < brkIx) // String entirely in bldr builder
return bldr.ToString(start - minIx, limit - start);
else if (start >= brkIx) // String entirely in next builder
return next.ToString(start - brkIx, limit - start);
else // Must do a string-concatenation
return
bldr.ToString(start - minIx, brkIx - start) +
next.ToString(0, limit - brkIx);
else
throw new BufferException("String was outside data buffer");
}
internal void Mark(int limit)
{
if (limit > brkIx + 16) // Rotate blocks
{
StringBuilder temp = bldr;
bldr = next;
next = temp;
next.Length = 0;
minIx = brkIx;
brkIx = maxIx;
}
}
}
BufferElement data = new BufferElement();
int bPos; // Postion index in the StringBuilder
BlockReader NextBlk; // Delegate that serves char-arrays;
private string EncodingName
{
get
{
StreamReader rdr = NextBlk.Target as StreamReader;
return (rdr == null ? "raw-bytes" : rdr.CurrentEncoding.BodyName);
}
}
public BuildBuffer(Stream stream)
{
FileStream fStrm = (stream as FileStream);
if (fStrm != null) FileName = fStrm.Name;
NextBlk = BlockReaderFactory.Raw(stream);
}
#if (!BYTEMODE)
public BuildBuffer(Stream stream, int fallbackCodePage)
{
FileStream fStrm = (stream as FileStream);
if (fStrm != null) FileName = fStrm.Name;
NextBlk = BlockReaderFactory.Get(stream, fallbackCodePage);
}
#endif
/// <summary>
/// Marks a conservative lower bound for the buffer,
/// allowing space to be reclaimed. If an application
/// needs to call GetString at arbitrary past locations
/// in the input stream, Mark() is not called.
/// </summary>
public override void Mark() { data.Mark(bPos - 2); }
public override int Pos
{
get { return bPos; }
set { bPos = value; }
}
/// <summary>
/// Read returns the ordinal number of the next char, or
/// EOF (-1) for an end of stream. Note that the next
/// code point may require *two* calls of Read().
/// </summary>
/// <returns></returns>
public override int Read()
{
//
// Characters at positions
// [data.offset, data.offset + data.bldr.Length)
// are available in data.bldr.
//
if (bPos < data.MaxIndex)
{
// ch0 cannot be EOF
return (int)data[bPos++];
}
else // Read from underlying stream
{
// Experimental code, blocks of page size
char[] chrs = new char[4096];
int count = NextBlk(chrs, 0, 4096);
if (count == 0)
return EndOfFile;
else
{
data.Append(chrs, count);
return (int)data[bPos++];
}
}
}
public override string GetString(int begin, int limit)
{
return data.GetString(begin, limit);
}
public override string ToString()
{
return "StringBuilder buffer, encoding: " + this.EncodingName;
}
}
// =============== End ScanBuff-derived classes ==================
internal delegate int BlockReader(char[] block, int index, int number);
// A delegate factory, serving up a delegate that
// reads a block of characters from the underlying
// encoded stream, via a StreamReader object.
//
internal static class BlockReaderFactory
{
public static BlockReader Raw(Stream stream)
{
return delegate(char[] block, int index, int number)
{
byte[] b = new byte[number];
int count = stream.Read(b, 0, number);
int i = 0;
int j = index;
for (; i < count; i++, j++)
block[j] = (char)b[i];
return count;
};
}
#if (!BYTEMODE)
public static BlockReader Get(Stream stream, int fallbackCodePage)
{
Encoding encoding;
int preamble = Preamble(stream);
if (preamble != 0) // There is a valid BOM here!
encoding = Encoding.GetEncoding(preamble);
else if (fallbackCodePage == -1) // Fallback is "raw" bytes
return Raw(stream);
else if (fallbackCodePage != -2) // Anything but "guess"
encoding = Encoding.GetEncoding(fallbackCodePage);
else // This is the "guess" option
{
int guess = new Guesser(stream).GuessCodePage();
stream.Seek(0, SeekOrigin.Begin);
if (guess == -1) // ==> this is a 7-bit file
encoding = Encoding.ASCII;
else if (guess == 65001)
encoding = Encoding.UTF8;
else // ==> use the machine default
encoding = Encoding.Default;
}
StreamReader reader = new StreamReader(stream, encoding);
return reader.Read;
}
static int Preamble(Stream stream)
{
int b0 = stream.ReadByte();
int b1 = stream.ReadByte();
if (b0 == 0xfe && b1 == 0xff)
return 1201; // UTF16BE
if (b0 == 0xff && b1 == 0xfe)
return 1200; // UTF16LE
int b2 = stream.ReadByte();
if (b0 == 0xef && b1 == 0xbb && b2 == 0xbf)
return 65001; // UTF8
//
// There is no unicode preamble, so we
// return denoter for the machine default.
//
stream.Seek(0, SeekOrigin.Begin);
return 0;
}
#endif // !BYTEMODE
}
#endif // !NOFILES
#endregion Buffer classes
// ==============================================================
// ============ class CodePageHandling =============
// ==============================================================
#if (!NOFILES)
public static class CodePageHandling
{
public static int GetCodePage(string option)
{
string command = option.ToUpperInvariant();
if (command.StartsWith("CodePage:", StringComparison.OrdinalIgnoreCase))
command = command.Substring(9);
try
{
if (command.Equals("RAW"))
return -1;
else if (command.Equals("GUESS"))
return -2;
else if (command.Equals("DEFAULT"))
return 0;
else if (char.IsDigit(command[0]))
return int.Parse(command, CultureInfo.InvariantCulture);
else
{
Encoding enc = Encoding.GetEncoding(command);
return enc.CodePage;
}
}
catch (FormatException)
{
Console.Error.WriteLine(
"Invalid format \"{0}\", using machine default", option);
}
catch (ArgumentException)
{
Console.Error.WriteLine(
"Unknown code page \"{0}\", using machine default", option);
}
return 0;
}
}
#region guesser
#if (!BYTEMODE)
// ==============================================================
// ============ Encoding Guesser =============
// ==============================================================
/// <summary>
/// This class provides a simple finite state automaton that
/// scans the file looking for (1) valid UTF-8 byte patterns,
/// (2) bytes >= 0x80 which are not part of a UTF-8 sequence.
/// The method then guesses whether it is UTF-8 or maybe some
/// local machine default encoding. This works well for the
/// various Latin encodings.
/// </summary>
internal class Guesser
{
ScanBuff buffer;
public int GuessCodePage() { return Scan(); }
const int maxAccept = 10;
const int initial = 0;
const int eofNum = 0;
const int goStart = -1;
const int INITIAL = 0;
const int EndToken = 0;
#region user code
/*
* Reads the bytes of a file to determine if it is
* UTF-8 or a single-byte code page file.
*/
public long utfX;
public long uppr;
#endregion user code
int state;
int currentStart = startState[0];
int code;
#region ScannerTables
static int[] startState = new int[] { 11, 0 };
#region CharacterMap
static sbyte[] map = new sbyte[256] {
/* '\0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '\x10' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '\x20' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '@' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 'P' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '`' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 'p' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '\x80' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\x90' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\xA0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\xB0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\xC0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* '\xD0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* '\xE0' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
/* '\xF0' */ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 };
#endregion
static sbyte[][] nextState = new sbyte[][] {
new sbyte[] {0, 0, 0, 0, 0, 0},
new sbyte[] {-1, -1, 10, -1, -1, -1},
new sbyte[] {-1, -1, -1, -1, -1, -1},
new sbyte[] {-1, -1, 8, -1, -1, -1},
new sbyte[] {-1, -1, 5, -1, -1, -1},
new sbyte[] {-1, -1, 6, -1, -1, -1},
new sbyte[] {-1, -1, 7, -1, -1, -1},
null,
new sbyte[] {-1, -1, 9, -1, -1, -1},
null,
null,
new sbyte[] {-1, 1, 2, 3, 4, 2}
};
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
// Reason for suppression: cannot have self-reference in array initializer.
static Guesser()
{
nextState[7] = nextState[2];
nextState[9] = nextState[2];
nextState[10] = nextState[2];
}
int NextState()
{
if (code == ScanBuff.EndOfFile)
return eofNum;
else
return nextState[state][map[code]];
}
#endregion
public Guesser(System.IO.Stream file) { SetSource(file); }
public void SetSource(System.IO.Stream source)
{
this.buffer = new BuildBuffer(source);
code = buffer.Read();
}
int Scan()
{
for (; ; )
{
int next;
state = currentStart;
while ((next = NextState()) == goStart)
code = buffer.Read();
state = next;
code = buffer.Read();
while ((next = NextState()) > eofNum)
{
state = next;
code = buffer.Read();
}
if (state <= maxAccept)
{
#region ActionSwitch
#pragma warning disable 162
switch (state)
{
case eofNum:
switch (currentStart)
{
case 11:
if (utfX == 0 && uppr == 0) return -1; /* raw ascii */
else if (uppr * 10 > utfX) return 0; /* default code page */
else return 65001; /* UTF-8 encoding */
break;
}
return EndToken;
case 1: // Recognized '{Upper128}', Shortest string "\xC0"
case 2: // Recognized '{Upper128}', Shortest string "\x80"
case 3: // Recognized '{Upper128}', Shortest string "\xE0"
case 4: // Recognized '{Upper128}', Shortest string "\xF0"
uppr++;
break;
case 5: // Recognized '{Utf8pfx4}{Utf8cont}', Shortest string "\xF0\x80"
uppr += 2;
break;
case 6: // Recognized '{Utf8pfx4}{Utf8cont}{2}', Shortest string "\xF0\x80\x80"
uppr += 3;
break;
case 7: // Recognized '{Utf8pfx4}{Utf8cont}{3}', Shortest string "\xF0\x80\x80\x80"
utfX += 3;
break;
case 8: // Recognized '{Utf8pfx3}{Utf8cont}', Shortest string "\xE0\x80"
uppr += 2;
break;
case 9: // Recognized '{Utf8pfx3}{Utf8cont}{2}', Shortest string "\xE0\x80\x80"
utfX += 2;
break;
case 10: // Recognized '{Utf8pfx2}{Utf8cont}', Shortest string "\xC0\x80"
utfX++;
break;
default:
break;
}
#pragma warning restore 162
#endregion
}
}
}
} // end class Guesser
#endif // !BYTEMODE
#endregion
#endif // !NOFILES
// End of code copied from embedded resource
}
@@ -0,0 +1,19 @@
namespace Bts.ArithmeticExpressions;
using System.Numerics;
public interface IArithmeticExpression {
IArithmeticExpression Add(IArithmeticExpression factor) => new Sum(this, factor);
IArithmeticExpression Divide(IArithmeticExpression other) => new Quotient(this, other);
IArithmeticExpression Multiply(IArithmeticExpression other) => new Product(this, other);
IArithmeticExpression Subtract(IArithmeticExpression other) => new Difference(this, other);
IArithmeticExpression Negate() => new AdditiveInverse(this);
object? Evaluate(IDictionary<string, object?> env);
}
public interface IArithmeticExpression<T> : IArithmeticExpression where T : INumber<T> {
new T Evaluate(IDictionary<string, object?> env);
object? IArithmeticExpression.Evaluate(IDictionary<string, object?> env) =>
Evaluate(env);
}
@@ -0,0 +1,7 @@
namespace Bts.ArithmeticExpressions;
public interface IArithmeticProgram {
IEnumerable<string> OutputIdentifiers { get; }
IDictionary<string, object?> Evaluate(IDictionary<string, object?> env);
}
@@ -0,0 +1,11 @@
namespace Bts.ArithmeticExpressions;
class IntegerConstant : IArithmeticExpression<int> {
readonly int value;
public IntegerConstant(int value) =>
this.value = value;
public int Evaluate(IDictionary<string, object?> env) =>
value;
}
@@ -0,0 +1,45 @@
namespace Bts.ArithmeticExpressions;
using System.Numerics;
class Product : IArithmeticExpression<double> {
readonly IArithmeticExpression left;
readonly IArithmeticExpression right;
public Product(IArithmeticExpression left, IArithmeticExpression right) {
this.left = left;
this.right = right;
}
public static Product<T, T, T> Create<T>(
IArithmeticExpression<T> left, IArithmeticExpression<T> right)
where T : INumber<T>, IMultiplyOperators<T, T, T> =>
new(left, right);
public double Evaluate(IDictionary<string, object?> env) =>
evaluateArg(left, nameof(left), env) * evaluateArg(right, nameof(right), env);
static double evaluateArg(
IArithmeticExpression expr, string name, IDictionary<string, object?> env) {
var obj = expr.Evaluate(env);
return ConvertUtils.try_convert(expr.Evaluate(env), out double dbl) ? dbl :
throw new Exception(
$"Invalid Product. {name} is of type {obj?.GetType()} (expected {typeof(double)})");
}
}
class Product<TLeft, TRight, TResult> : IArithmeticExpression<TResult>
where TLeft : INumber<TLeft>, IMultiplyOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> {
readonly IArithmeticExpression<TLeft> left;
readonly IArithmeticExpression<TRight> right;
public Product(IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right) {
this.left = left;
this.right = right;
}
public TResult Evaluate(IDictionary<string, object?> env) =>
left.Evaluate(env) * right.Evaluate(env);
}
@@ -0,0 +1,45 @@
namespace Bts.ArithmeticExpressions;
using System.Numerics;
class Quotient : IArithmeticExpression<double> {
readonly IArithmeticExpression left;
readonly IArithmeticExpression right;
public Quotient(IArithmeticExpression left, IArithmeticExpression right) {
this.left = left;
this.right = right;
}
public static Quotient<T, T, T> Create<T>(
IArithmeticExpression<T> left, IArithmeticExpression<T> right)
where T : INumber<T>, IDivisionOperators<T, T, T> =>
new(left, right);
public double Evaluate(IDictionary<string, object?> env) =>
evaluateArg(left, nameof(left), env) / evaluateArg(right, nameof(right), env);
static double evaluateArg(
IArithmeticExpression expr, string name, IDictionary<string, object?> env) {
var obj = expr.Evaluate(env);
return ConvertUtils.try_convert(expr.Evaluate(env), out double dbl) ? dbl :
throw new Exception(
$"Invalid Quotient. {name} is of type {obj?.GetType()} (expected {typeof(double)})");
}
}
class Quotient<TLeft, TRight, TResult> : IArithmeticExpression<TResult>
where TLeft : INumber<TLeft>, IDivisionOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> {
readonly IArithmeticExpression<TLeft> left;
readonly IArithmeticExpression<TRight> right;
public Quotient(IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right) {
this.left = left;
this.right = right;
}
public TResult Evaluate(IDictionary<string, object?> env) =>
left.Evaluate(env) / right.Evaluate(env);
}
@@ -0,0 +1,11 @@
namespace Bts.ArithmeticExpressions;
class RealConstant : IArithmeticExpression<double> {
readonly double value;
public RealConstant(double value) =>
this.value = value;
public double Evaluate(IDictionary<string, object?> env) =>
value;
}
@@ -0,0 +1,884 @@
// ==============================================================
// <auto-generated>
// This code automatically produced from an embedded resource.
// Do not edit this file, or it will become incompatible with
// the specification from which it was generated.
// </auto-generated>
// ==============================================================
// Gardens Point Parser Generator
// Copyright (c) Wayne Kelly, QUT 2005-2010
// (see accompanying GPPGcopyright.rtf)
using System;
using System.Text;
using System.Globalization;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
namespace QUT.Gppg {
/// <summary>
/// Abstract class for GPPG shift-reduce parsers.
/// Parsers generated by GPPG derive from this base
/// class, overriding the abstract Initialize() and
/// DoAction() methods.
/// </summary>
/// <typeparam name="TValue">Semantic value type</typeparam>
/// <typeparam name="TSpan">Location type</typeparam>
#if EXPORT_GPPG
public abstract class ShiftReduceParser<TValue, TSpan>
#else
internal abstract class ShiftReduceParser<TValue, TSpan>
#endif
where TSpan : IMerge<TSpan>, new() {
private AbstractScanner<TValue, TSpan> scanner;
/// <summary>
/// The abstract scanner for this parser.
/// </summary>
protected AbstractScanner<TValue, TSpan> Scanner {
get { return scanner; }
set { scanner = value; }
}
/// <summary>
/// Constructor for base class
/// </summary>
/// <param name="scanner">Scanner instance for this parser</param>
protected ShiftReduceParser( AbstractScanner<TValue, TSpan> scanner ) {
this.scanner = scanner;
}
// ==============================================================
// TECHNICAL EXPLANATION.
// Why the next two fields are not exposed via properties.
// ==============================================================
// These fields are of the generic parameter types, and are
// frequently instantiated as struct types in derived classes.
// Semantic actions are defined in the derived classes and refer
// to instance fields of these structs. In such cases the code
// "get_CurrentSemanticValue().myField = blah;" will fail since
// the getter pushes the value of the field, not the reference.
// So, in the presence of properties, gppg would need to encode
// such field accesses as ...
// "tmp = get_CurrentSemanticValue(); // Fetch value
// tmp.myField = blah; // update
// set_CurrentSemanticValue(tmp); " // Write update back.
// There is no issue if TValue is restricted to be a ref type.
// The same explanation applies to scanner.yylval.
// ==============================================================
/// <summary>
/// The current value of the "$$" symbolic variable in the parser
/// </summary>
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
protected TValue CurrentSemanticValue;
/// <summary>
/// The current value of the "@$" symbolic variable in the parser
/// </summary>
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
protected TSpan CurrentLocationSpan;
protected int NextToken;
private TSpan LastSpan;
private State FsaState;
private bool recovering;
private int tokensSinceLastError;
private PushdownPrefixState<State> StateStack = new PushdownPrefixState<State>();
private PushdownPrefixState<TValue> valueStack = new PushdownPrefixState<TValue>();
private PushdownPrefixState<TSpan> locationStack = new PushdownPrefixState<TSpan>();
/// <summary>
/// The stack of semantic value (YYSTYPE) values.
/// </summary>
protected PushdownPrefixState<TValue> ValueStack { get { return valueStack; } }
/// <summary>
/// The stack of location value (YYLTYPE) varlues.
/// </summary>
protected PushdownPrefixState<TSpan> LocationStack { get { return locationStack; } }
private int errorToken;
private int endOfFileToken;
private string[] nonTerminals;
private State[] states;
private Rule[] rules;
/// <summary>
/// Initialization method to allow derived classes
/// to insert the rule list into this base class.
/// </summary>
/// <param name="rules">The array of Rule objects</param>
protected void InitRules( Rule[] rules ) { this.rules = rules; }
/// <summary>
/// Initialization method to allow derived classes to
/// insert the states table into this base class.
/// </summary>
/// <param name="states">The pre-initialized states table</param>
protected void InitStates( State[] states ) { this.states = states; }
/// <summary>
/// OBSOLETE FOR VERSION 1.4.0
/// </summary>
/// <param name="size"></param>
protected void InitStateTable( int size ) { states = new State[size]; }
/// <summary>
/// Initialization method to allow derived classes
/// to insert the special value for the error and EOF tokens.
/// </summary>
/// <param name="err">The error state ordinal</param>
/// <param name="end">The EOF stat ordinal</param>
protected void InitSpecialTokens( int err, int end ) {
errorToken = err;
endOfFileToken = end;
}
/// <summary>
/// Initialization method to allow derived classes to
/// insert the non-terminal symbol names into this base class.
/// </summary>
/// <param name="names">Non-terminal symbol names</param>
protected void InitNonTerminals( string[] names ) { nonTerminals = names; }
#region YYAbort, YYAccept etcetera.
[Serializable]
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
// Reason for FxCop message suppression -
// This exception cannot escape from the local context
private class AcceptException : Exception {
internal AcceptException() { }
protected AcceptException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
}
[Serializable]
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
// Reason for FxCop message suppression -
// This exception cannot escape from the local context
private class AbortException : Exception {
internal AbortException() { }
protected AbortException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
}
[Serializable]
[SuppressMessage( "Microsoft.Design", "CA1064:ExceptionsShouldBePublic" )]
// Reason for FxCop message suppression -
// This exception cannot escape from the local context
private class ErrorException : Exception {
internal ErrorException() { }
protected ErrorException( SerializationInfo i, StreamingContext c ) : base( i, c ) { }
}
// The following methods are only called from within
// a semantic action. The thrown exceptions can never
// propagate outside the ShiftReduceParser class in
// which they are nested.
/// <summary>
/// Force parser to terminate, returning "true"
/// </summary>
protected static void YYAccept() { throw new AcceptException(); }
/// <summary>
/// Force parser to terminate, returning "false"
/// </summary>
protected static void YYAbort() { throw new AbortException(); }
/// <summary>
/// Force parser to terminate, returning
/// "false" if error recovery fails.
/// </summary>
protected static void YYError() { throw new ErrorException(); }
/// <summary>
/// Check if parser in error recovery state.
/// </summary>
protected bool YYRecovering { get { return recovering; } }
#endregion
/// <summary>
/// Abstract base method. ShiftReduceParser calls this
/// to initialize the base class data structures. Concrete
/// parser classes must override this method.
/// </summary>
protected abstract void Initialize();
/// <summary>
/// Main entry point of the Shift-Reduce Parser.
/// </summary>
/// <returns>True if parse succeeds, else false for
/// unrecoverable errors</returns>
public bool Parse() {
Initialize(); // allow derived classes to instantiate rules, states and nonTerminals
NextToken = 0;
FsaState = states[0];
StateStack.Push( FsaState );
valueStack.Push( CurrentSemanticValue );
LocationStack.Push( CurrentLocationSpan );
while (true) {
#if TRACE_ACTIONS
Console.Error.WriteLine("Entering state {0} ", FsaState.number);
DisplayStack();
#endif
int action = FsaState.defaultAction;
if (FsaState.ParserTable != null) {
if (NextToken == 0) {
// We save the last token span, so that the location span
// of production right hand sides that begin or end with a
// nullable production will be correct.
LastSpan = scanner.yylloc;
NextToken = scanner.yylex();
#if TRACE_ACTIONS
Console.Error.WriteLine( "Reading: Next token is {0}", TerminalToString( NextToken ) );
#endif
}
#if TRACE_ACTIONS
else
Console.Error.WriteLine( "Next token is still {0}", TerminalToString( NextToken ) );
#endif
if (FsaState.ParserTable.ContainsKey( NextToken ))
action = FsaState.ParserTable[NextToken];
}
if (action > 0) // shift
{
Shift( action );
}
else if (action < 0) // reduce
{
try {
Reduce( -action );
if (action == -1) // accept
return true;
}
catch (AbortException) {
return false;
}
catch (AcceptException) {
return true;
}
catch (ErrorException) {
if (!ErrorRecovery())
return false;
else
throw; // Rethrow x, preserving information.
}
}
else if (action == 0 && !ErrorRecovery()) // error
return false;
}
}
private void Shift( int stateIndex ) {
#if TRACE_ACTIONS
Console.Error.Write("Shifting token {0}, ", TerminalToString(NextToken));
#endif
FsaState = states[stateIndex];
valueStack.Push( scanner.yylval );
StateStack.Push( FsaState );
LocationStack.Push( scanner.yylloc );
if (recovering) {
if (NextToken != errorToken)
tokensSinceLastError++;
if (tokensSinceLastError > 5)
recovering = false;
}
if (NextToken != endOfFileToken)
NextToken = 0;
}
private void Reduce( int ruleNumber ) {
#if TRACE_ACTIONS
DisplayRule(ruleNumber);
#endif
Rule rule = rules[ruleNumber];
int rhLen = rule.RightHandSide.Length;
//
// Default actions for unit productions.
//
if (rhLen == 1) {
CurrentSemanticValue = valueStack.TopElement(); // Default action: $$ = $1;
CurrentLocationSpan = LocationStack.TopElement(); // Default action "@$ = @1;
}
else if (rhLen == 0) {
// Create a new blank value.
// Explicit semantic action may mutate this value
CurrentSemanticValue = default( TValue );
// The location span for an empty production will start with the
// beginning of the next lexeme, and end with the finish of the
// previous lexeme. This gives the correct behaviour when this
// nonsense value is used in later Merge operations.
CurrentLocationSpan = (scanner.yylloc != null && LastSpan != null ?
scanner.yylloc.Merge( LastSpan ) :
default( TSpan ));
}
else {
// Default action: $$ = $1;
CurrentSemanticValue = valueStack[LocationStack.Depth - rhLen];
// Default action "@$ = @1.Merge(@N)" for location info.
TSpan at1 = LocationStack[LocationStack.Depth - rhLen];
TSpan atN = LocationStack[LocationStack.Depth - 1];
CurrentLocationSpan =
((at1 != null && atN != null) ? at1.Merge( atN ) : default( TSpan ));
}
DoAction( ruleNumber );
for (int i = 0; i < rule.RightHandSide.Length; i++) {
StateStack.Pop();
valueStack.Pop();
LocationStack.Pop();
}
FsaState = StateStack.TopElement();
if (FsaState.Goto.ContainsKey( rule.LeftHandSide ))
FsaState = states[FsaState.Goto[rule.LeftHandSide]];
StateStack.Push( FsaState );
valueStack.Push( CurrentSemanticValue );
LocationStack.Push( CurrentLocationSpan );
}
/// <summary>
/// Execute the selected action from array.
/// Must be overriden in derived classes.
/// </summary>
/// <param name="actionNumber">Index of the action to perform</param>
protected abstract void DoAction( int actionNumber );
private bool ErrorRecovery() {
bool discard;
if (!recovering) // if not recovering from previous error
ReportError();
if (!FindErrorRecoveryState())
return false;
//
// The interim fix for the "looping in error recovery"
// artifact involved moving the setting of the recovering
// bool until after invalid tokens have been discarded.
//
ShiftErrorToken();
discard = DiscardInvalidTokens();
recovering = true;
tokensSinceLastError = 0;
return discard;
}
private void ReportError() {
StringBuilder errorMsg = new StringBuilder();
errorMsg.AppendFormat( "Syntax error, unexpected {0}", TerminalToString( NextToken ) );
if (FsaState.ParserTable.Count < 7) {
bool first = true;
foreach (int terminal in FsaState.ParserTable.Keys) {
if (first)
errorMsg.Append( ", expecting " );
else
errorMsg.Append( ", or " );
errorMsg.Append( TerminalToString( terminal ) );
first = false;
}
}
scanner.yyerror( errorMsg.ToString() );
}
private void ShiftErrorToken() {
int old_next = NextToken;
NextToken = errorToken;
Shift( FsaState.ParserTable[NextToken] );
#if TRACE_ACTIONS
Console.Error.WriteLine("Entering state {0} ", FsaState.number);
#endif
NextToken = old_next;
}
private bool FindErrorRecoveryState() {
while (true) // pop states until one found that accepts error token
{
if (FsaState.ParserTable != null &&
FsaState.ParserTable.ContainsKey( errorToken ) &&
FsaState.ParserTable[errorToken] > 0) // shift
return true;
#if TRACE_ACTIONS
Console.Error.WriteLine("Error: popping state {0}", StateStack.TopElement().number);
#endif
StateStack.Pop();
valueStack.Pop();
LocationStack.Pop();
#if TRACE_ACTIONS
DisplayStack();
#endif
if (StateStack.IsEmpty()) {
#if TRACE_ACTIONS
Console.Error.WriteLine("Aborting: didn't find a state that accepts error token");
#endif
return false;
}
else
FsaState = StateStack.TopElement();
}
}
private bool DiscardInvalidTokens() {
int action = FsaState.defaultAction;
if (FsaState.ParserTable != null) {
// Discard tokens until find one that works ...
while (true) {
if (NextToken == 0) {
#if TRACE_ACTIONS
Console.Error.Write("Reading a token: ");
#endif
NextToken = scanner.yylex();
}
#if TRACE_ACTIONS
Console.Error.WriteLine("Next token is {0}", TerminalToString(NextToken));
#endif
if (NextToken == endOfFileToken)
return false;
if (FsaState.ParserTable.ContainsKey( NextToken ))
action = FsaState.ParserTable[NextToken];
if (action != 0)
return true;
else {
#if TRACE_ACTIONS
Console.Error.WriteLine("Error: Discarding {0}", TerminalToString(NextToken));
#endif
NextToken = 0;
}
}
}
else if (recovering && tokensSinceLastError == 0) {
//
// Boolean recovering is not set until after the first
// error token has been shifted. Thus if we get back
// here with recovering set and no tokens read we are
// looping on the same error recovery action. This
// happens if current_state.ParserTable is null because
// the state has an LR(0) reduction, but not all
// lookahead tokens are valid. This only occurs for
// error productions that *end* on "error".
//
// This action discards tokens one at a time until
// the looping stops. Another attack would be to always
// use the LALR(1) table if a production ends on "error"
//
#if TRACE_ACTIONS
Console.Error.WriteLine("Error: panic discard of {0}", TerminalToString(NextToken));
#endif
if (NextToken == endOfFileToken)
return false;
NextToken = 0;
return true;
}
else
return true;
}
/// <summary>
/// Traditional YACC method. Discards the next input token.
/// </summary>
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyclearin" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyclearin" )]
// Reason for FxCop message suppression -
// This is a traditional name for YACC-like functionality
protected void yyclearin() { NextToken = 0; }
/// <summary>
/// Tradional YACC method. Clear the "recovering" flag.
/// </summary>
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyerrok" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyerrok" )]
// Reason for FxCop message suppression -
// This is a traditional name for YACC-like functionality
protected void yyerrok() { recovering = false; }
/// <summary>
/// OBSOLETE FOR VERSION 1.4.0
/// Method used by derived types to insert new
/// state instances in the "states" array.
/// </summary>
/// <param name="stateNumber">index of the state</param>
/// <param name="state">data for the state</param>
protected void AddState( int stateNumber, State state ) {
states[stateNumber] = state;
state.number = stateNumber;
}
private void DisplayStack() {
Console.Error.Write( "State stack is now:" );
for (int i = 0; i < StateStack.Depth; i++)
Console.Error.Write( " {0}", StateStack[i].number );
Console.Error.WriteLine();
}
private void DisplayRule( int ruleNumber ) {
Console.Error.Write( "Reducing stack by rule {0}, ", ruleNumber );
DisplayProduction( rules[ruleNumber] );
}
private void DisplayProduction( Rule rule ) {
if (rule.RightHandSide.Length == 0)
Console.Error.Write( "/* empty */ " );
else
foreach (int symbol in rule.RightHandSide)
Console.Error.Write( "{0} ", SymbolToString( symbol ) );
Console.Error.WriteLine( "-> {0}", SymbolToString( rule.LeftHandSide ) );
}
/// <summary>
/// Abstract state class naming terminal symbols.
/// This is overridden by derived classes with the
/// name (or alias) to be used in error messages.
/// </summary>
/// <param name="terminal">The terminal ordinal</param>
/// <returns></returns>
protected abstract string TerminalToString( int terminal );
private string SymbolToString( int symbol ) {
if (symbol < 0)
return nonTerminals[-symbol - 1];
else
return TerminalToString( symbol );
}
/// <summary>
/// Return text representation of argument character
/// </summary>
/// <param name="input">The character to convert</param>
/// <returns>String representation of the character</returns>
protected static string CharToString( char input ) {
switch (input) {
case '\a': return @"'\a'";
case '\b': return @"'\b'";
case '\f': return @"'\f'";
case '\n': return @"'\n'";
case '\r': return @"'\r'";
case '\t': return @"'\t'";
case '\v': return @"'\v'";
case '\0': return @"'\0'";
default: return string.Format( CultureInfo.InvariantCulture, "'{0}'", input );
}
}
}
/// <summary>
/// Classes implementing this interface must supply a
/// method that merges two location objects to return
/// a new object of the same type.
/// GPPG-generated parsers have the default location
/// action equivalent to "@$ = @1.Merge(@N);" where N
/// is the right-hand-side length of the production.
/// </summary>
/// <typeparam name="TSpan">The Location type</typeparam>
#if EXPORT_GPPG
public interface IMerge<TSpan>
#else
internal interface IMerge<TSpan>
#endif
{
/// <summary>
/// Interface method that creates a location object from
/// the current and last object. Typically used to create
/// a location object extending from the start of the @1
/// object to the end of the @N object.
/// </summary>
/// <param name="last">The lexically last object to merge</param>
/// <returns>The merged location object</returns>
TSpan Merge( TSpan last );
}
/// <summary>
/// This is the default class that carries location
/// information from the scanner to the parser.
/// If you don't declare "%YYLTYPE Foo" the parser
/// will expect to deal with this type.
/// </summary>
#if EXPORT_GPPG
public class LexLocation : IMerge<LexLocation>
#else
[SuppressMessage( "Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses" )]
internal class LexLocation : IMerge<LexLocation>
#endif
{
private int startLine; // start line
private int startColumn; // start column
private int endLine; // end line
private int endColumn; // end column
/// <summary>
/// The line at which the text span starts.
/// </summary>
public int StartLine { get { return startLine; } }
/// <summary>
/// The column at which the text span starts.
/// </summary>
public int StartColumn { get { return startColumn; } }
/// <summary>
/// The line on which the text span ends.
/// </summary>
public int EndLine { get { return endLine; } }
/// <summary>
/// The column of the first character
/// beyond the end of the text span.
/// </summary>
public int EndColumn { get { return endColumn; } }
/// <summary>
/// Default no-arg constructor.
/// </summary>
public LexLocation() { }
/// <summary>
/// Constructor for text-span with given start and end.
/// </summary>
/// <param name="sl">start line</param>
/// <param name="sc">start column</param>
/// <param name="el">end line </param>
/// <param name="ec">end column</param>
public LexLocation( int sl, int sc, int el, int ec ) { startLine = sl; startColumn = sc; endLine = el; endColumn = ec; }
/// <summary>
/// Create a text location which spans from the
/// start of "this" to the end of the argument "last"
/// </summary>
/// <param name="last">The last location in the result span</param>
/// <returns>The merged span</returns>
public LexLocation Merge( LexLocation last ) { return new LexLocation( this.startLine, this.startColumn, last.endLine, last.endColumn ); }
}
/// <summary>
/// Abstract scanner class that GPPG expects its scanners to
/// extend.
/// </summary>
/// <typeparam name="TValue">Semantic value type YYSTYPE</typeparam>
/// <typeparam name="TSpan">Source location type YYLTYPE</typeparam>
#if EXPORT_GPPG
public abstract class AbstractScanner<TValue, TSpan>
#else
internal abstract class AbstractScanner<TValue, TSpan>
#endif
where TSpan : IMerge<TSpan> {
/// <summary>
/// Lexical value optionally set by the scanner. The value
/// is of the %YYSTYPE type declared in the parser spec.
/// </summary>
[SuppressMessage( "Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields" )]
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylval" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylval" )]
// Reason for FxCop message suppression -
// This is a traditional name for YACC-like functionality
// A field must be declared for this value of parametric type,
// since it may be instantiated by a value struct. If it were
// implemented as a property, machine generated code in derived
// types would not be able to select on the returned value.
#pragma warning disable 649
public TValue yylval; // Lexical value: set by scanner
#pragma warning restore 649
/// <summary>
/// Current scanner location property. The value is of the
/// type declared by %YYLTYPE in the parser specification.
/// </summary>
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylloc" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylloc" )]
// Reason for FxCop message suppression -
// This is a traditional name for YACC-like functionality
public virtual TSpan yylloc {
get { return default( TSpan ); } // Empty implementation allowing
set { /* skip */ } // yylloc to be ignored entirely.
}
/// <summary>
/// Main call point for LEX-like scanners. Returns an int
/// corresponding to the token recognized by the scanner.
/// </summary>
/// <returns>An int corresponding to the token</returns>
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yylex" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yylex" )]
// Reason for FxCop message suppression -
// This is a traditional name for YACC-like functionality
public abstract int yylex();
/// <summary>
/// Traditional error reporting provided by LEX-like scanners
/// to their YACC-like clients.
/// </summary>
/// <param name="format">Message format string</param>
/// <param name="args">Optional array of args</param>
[SuppressMessage( "Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyerror" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyerror" )]
// Reason for FxCop message suppression -
// This is a traditional name for YACC-like functionality
public virtual void yyerror( string format, params object[] args ) { }
}
/// <summary>
/// Encapsulated state for the parser.
/// Opaque to users, visible to the tool-generated code.
/// </summary>
#if EXPORT_GPPG
public class State
{
/// <summary>
/// The number of states in the automaton.
/// </summary>
public int number;
#else
internal class State {
/// <summary>
/// The index of this state in the states array.
/// </summary>
internal int number;
#endif
internal Dictionary<int, int> ParserTable; // Terminal -> ParseAction
internal Dictionary<int, int> Goto; // NonTerminal -> State;
internal int defaultAction; // = 0; // ParseAction
/// <summary>
/// State transition data for this state. Pairs of elements of the
/// goto array associate symbol ordinals with next state indices.
/// The actions array is passed to another constructor.
/// </summary>
/// <param name="actions">The action list</param>c
/// <param name="goToList">Next state data</param>
public State( int[] actions, int[] goToList )
: this( actions ) {
Goto = new Dictionary<int, int>();
for (int i = 0; i < goToList.Length; i += 2)
Goto.Add( goToList[i], goToList[i + 1] );
}
/// <summary>
/// Action data for this state. Pairs of elements of the
/// action array associate action ordinals with each of
/// those symbols that have actions in the current state.
/// </summary>
/// <param name="actions">The action array</param>
public State( int[] actions ) {
ParserTable = new Dictionary<int, int>();
for (int i = 0; i < actions.Length; i += 2)
ParserTable.Add( actions[i], actions[i + 1] );
}
/// <summary>
/// Set the default action for this state.
/// </summary>
/// <param name="defaultAction">Ordinal of the default action</param>
public State( int defaultAction ) {
this.defaultAction = defaultAction;
}
/// <summary>
/// Set the default action and the state transition table.
/// </summary>
/// <param name="defaultAction">The default action</param>
/// <param name="goToList">Transitions from this state</param>
public State( int defaultAction, int[] goToList )
: this( defaultAction ) {
Goto = new Dictionary<int, int>();
for (int i = 0; i < goToList.Length; i += 2)
Goto.Add( goToList[i], goToList[i + 1] );
}
}
/// <summary>
/// Rule representation at runtime.
/// </summary>
#if EXPORT_GPPG
public class Rule
#else
internal class Rule
#endif
{
internal int LeftHandSide; // symbol
internal int[] RightHandSide; // symbols
/// <summary>
/// Rule constructor. This holds the ordinal of
/// the left hand side symbol, and the list of
/// right hand side symbols, in lexical order.
/// </summary>
/// <param name="left">The LHS non-terminal</param>
/// <param name="right">The RHS symbols, in lexical order</param>
public Rule( int left, int[] right ) {
this.LeftHandSide = left;
this.RightHandSide = right;
}
}
/// <summary>
/// Stack utility for the shift-reduce parser.
/// GPPG parsers have three instances:
/// (1) The parser state stack, T = QUT.Gppg.State,
/// (2) The semantic value stack, T = TValue,
/// (3) The location stack, T = TSpan.
/// </summary>
/// <typeparam name="T"></typeparam>
#if EXPORT_GPPG
public class PushdownPrefixState<T>
#else
internal class PushdownPrefixState<T>
#endif
{
// Note that we cannot use the BCL Stack<T> class
// here as derived types need to index into stacks.
//
private T[] array = new T[8];
private int tos = 0;
/// <summary>
/// Indexer for values of the stack below the top.
/// </summary>
/// <param name="index">index of the element, starting from the bottom</param>
/// <returns>the selected element</returns>
public T this[int index] { get { return array[index]; } }
/// <summary>
/// The current depth of the stack.
/// </summary>
public int Depth { get { return tos; } }
internal void Push( T value ) {
if (tos >= array.Length) {
T[] newarray = new T[array.Length * 2];
System.Array.Copy( array, newarray, tos );
array = newarray;
}
array[tos++] = value;
}
internal T Pop() {
T rslt = array[--tos];
array[tos] = default( T );
return rslt;
}
internal T TopElement() { return array[tos - 1]; }
internal bool IsEmpty() { return tos == 0; }
}
}
@@ -0,0 +1,45 @@
namespace Bts.ArithmeticExpressions;
using System.Numerics;
class Sum : IArithmeticExpression<double> {
readonly IArithmeticExpression left;
readonly IArithmeticExpression right;
public Sum(IArithmeticExpression left, IArithmeticExpression right) {
this.left = left;
this.right = right;
}
public static Sum<T, T, T> Create<T>(
IArithmeticExpression<T> left, IArithmeticExpression<T> right)
where T : INumber<T>, IAdditionOperators<T, T, T> =>
new(left, right);
public double Evaluate(IDictionary<string, object?> env) =>
evaluateArg(left, nameof(left), env) + evaluateArg(right, nameof(right), env);
static double evaluateArg(
IArithmeticExpression expr, string name, IDictionary<string, object?> env) {
var obj = expr.Evaluate(env);
return ConvertUtils.try_convert(expr.Evaluate(env), out double dbl) ? dbl :
throw new Exception(
$"Invalid Sum. {name} is of type {obj?.GetType()} (expected {typeof(double)})");
}
}
class Sum<TLeft, TRight, TResult> : IArithmeticExpression<TResult>
where TLeft : INumber<TLeft>, IAdditionOperators<TLeft, TRight, TResult>
where TRight : INumber<TRight>
where TResult : INumber<TResult> {
readonly IArithmeticExpression<TLeft> left;
readonly IArithmeticExpression<TRight> right;
public Sum(IArithmeticExpression<TLeft> left, IArithmeticExpression<TRight> right) {
this.left = left;
this.right = right;
}
public TResult Evaluate(IDictionary<string, object?> env) =>
left.Evaluate(env) + right.Evaluate(env);
}
@@ -0,0 +1,4 @@
global using System;
global using System.Linq;
global using System.Collections.Generic;
global using System.Collections.Immutable;
@@ -0,0 +1,15 @@
namespace Bts.ArithmeticExpressions;
using System.Collections.Generic;
class Variable : IArithmeticExpression {
readonly string identifier;
public Variable(string identifier) =>
this.identifier = identifier;
public object? Evaluate(IDictionary<string, object?> env) =>
env.TryGetValue(identifier, out var val) ? val :
throw new KeyNotFoundException(
$"Failed to find {nameof(Variable)} '{identifier}'");
}
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,41 @@
using mbts.spark;
using System;
using System.Runtime;
namespace BCG.Utilities.General
{
/// <summary>
/// Summary description for Crono.
/// </summary>
public class Crono
{
public Crono()
{
myTimer = new HighPerformanceTimer();
}
public void start()
{myTimer.start();}
public void stop()
{myTimer.stop();}
public TimeSpan time
{
get
{
return new TimeSpan((long) (myTimer.totalMilliseconds * TimeSpan.TicksPerMillisecond));
}
}
public double miliseconds
{
get
{return myTimer.totalMilliseconds;}
}
private HighPerformanceTimer myTimer;
}
}
@@ -0,0 +1,60 @@
using System;
using Microsoft.Win32;
namespace BCG
{
internal static class ArrayRegistryHandler
{
public static void setValue (RegistryKey rk, string name, Array array)
{
rk.SetValue (name, array.Length);
Type t = array.GetType ().GetElementType ();
for (int i = 0; i < array.Length; i++)
{
if (t == typeof (int))
rk.SetValue (string.Concat (name, i.ToString ()), (int) array.GetValue (i));
else if (t == typeof (bool))
rk.SetValue (string.Concat (name, i.ToString ()), (bool) array.GetValue (i));
else
rk.SetValue (string.Concat (name, i.ToString ()), array.GetValue (i));
}
}
public static Array getValue (RegistryKey rk, string name, Type elementType)
{
object c = rk.GetValue (name, 0);
int count = (int) c;
Array result;
if (elementType == typeof (int) || elementType == typeof (System.Int32))
result = new int[count];
else if (elementType == typeof (bool))
result = new bool[count];
else if (elementType == typeof (double))
result = new double[count];
else if (elementType == typeof (DateTime))
result = new DateTime[count];
else
result = new string[count];
for (int i = 0; i < count; i++)
{
object val = rk.GetValue (string.Concat (name, i.ToString ()));
if (elementType == typeof (int) || elementType == typeof (System.Int32))
result.SetValue (int.Parse (val.ToString ()), i);
else if (elementType == typeof (bool))
result.SetValue (bool.Parse (val.ToString ()), i);
else if (elementType == typeof (double))
result.SetValue (double.Parse (val.ToString ()), i);
else if (elementType == typeof (DateTime))
result.SetValue (DateTime.Parse (val.ToString ()), i);
else
result.SetValue (val.ToString (), i);
}
return result;
}
}
}
@@ -0,0 +1,192 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Reflection;
using Microsoft.Win32;
namespace BCG
{
public enum RegistryRoot { HKCU, HKLM }
[Serializable]
public class BlueRegistry
{
public const string BlueSubKey = @"Software\Blue Capital Group\";
public static readonly string ApplicationPrefix;
protected string myFullPath;
public BlueRegistry(string subPath)
{
myFullPath = string.Concat(BlueRegistry.ApplicationPrefix, @"\", subPath);
}
public BlueRegistry(BlueRegistry parent, string subPath)
{
myFullPath = string.Concat(parent.myFullPath, @"\", subPath);
}
static BlueRegistry()
{
string app = "Applications";
Assembly ass = Assembly.GetEntryAssembly();
if (ass != null)
{
app = ass.GetName().Name;
object[] attrs = ass.GetCustomAttributes(
Type.GetType("System.Reflection.AssemblyTitleAttribute"), true);
if (attrs.Length > 0 && ((AssemblyTitleAttribute)attrs[0]).Title != string.Empty)
{
app = ((AssemblyTitleAttribute)attrs[0]).Title;
}
}
ApplicationPrefix = string.Concat(BlueRegistry.BlueSubKey, app);
}
public object getValue(string name)
{
return getValue(RegistryRoot.HKCU, name);
}
public object getValue(string name, object defaultValue)
{
return getValue(RegistryRoot.HKCU, name, defaultValue);
}
public void setValue(string name, object value)
{
setValue(RegistryRoot.HKCU, name, value);
}
public void deleteValue(string name)
{
deleteValue(RegistryRoot.HKCU, name);
}
private RegistryKey myGetRegistryKey(RegistryRoot root)
{
if (root == RegistryRoot.HKCU)
return Registry.CurrentUser.CreateSubKey(myFullPath);
else
return Registry.LocalMachine.CreateSubKey(myFullPath);
}
#region Generic Methods
internal virtual void setValue(RegistryRoot root, string name, object value)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
rk.SetValue(name, value);
}
}
internal virtual object getValue(RegistryRoot root, string name)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
return rk.GetValue(name);
}
}
internal virtual void deleteValue(RegistryRoot root, string name)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
rk.DeleteValue(name);
}
}
internal virtual object getValue(RegistryRoot root, string name, object defaultValue)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
return rk.GetValue(name, defaultValue);
}
}
#endregion
#region Double
internal virtual void setDouble(RegistryRoot root, string name, double value)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
DoubleRegistryHandler.setValue(rk, name, value);
}
}
internal virtual double getDouble(RegistryRoot root, string name)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
return DoubleRegistryHandler.getValue(rk, name);
}
}
#endregion
#region Enum
internal virtual void setEnum(RegistryRoot root, string name, Enum value)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
EnumRegistryHandler.setValue(rk, name, value);
}
}
internal virtual Enum getEnum(RegistryRoot root, string name, Type enumType)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
return EnumRegistryHandler.getValue(rk, name, enumType);
}
}
#endregion
#region Array
internal virtual void setArray(RegistryRoot root, string name, Array array)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
ArrayRegistryHandler.setValue(rk, name, array);
}
}
internal virtual Array getArray(RegistryRoot root, string name, Type elementType)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
return ArrayRegistryHandler.getValue(rk, name, elementType);
}
}
#endregion
#region SortedList
internal virtual void setSortedList(RegistryRoot root, string name, SortedList slist)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
SortedListRegistryHandler.setValue(rk, name, slist);
}
}
internal virtual SortedList getSortedList(RegistryRoot root, string name)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
return SortedListRegistryHandler.getValue(rk, name);
}
}
internal virtual void deleteSortedList(RegistryRoot root, string name)
{
using (RegistryKey rk = myGetRegistryKey(root))
{
SortedListRegistryHandler.deleteValue(rk, name);
}
}
#endregion
}
}
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
</Project>
@@ -0,0 +1,22 @@
using System;
using Microsoft.Win32;
namespace BCG
{
internal static class DoubleRegistryHandler
{
public static void setValue (RegistryKey rk, string name, double value)
{
rk.SetValue (name, value.ToString ());
}
public static double getValue (RegistryKey rk, string name)
{
object v = rk.GetValue (name);
if (v != null)
return double.Parse (v.ToString ());
else
return double.NaN;
}
}
}
@@ -0,0 +1,22 @@
using System;
using Microsoft.Win32;
namespace BCG
{
internal static class EnumRegistryHandler
{
public static void setValue (RegistryKey rk, string name, Enum value)
{
rk.SetValue (name, value.ToString ());
}
public static Enum getValue (RegistryKey rk, string name, Type enumType)
{
object v = rk.GetValue (name);
if (v != null)
return (Enum) Enum.Parse (enumType, v.ToString ());
else
return null;
}
}
}
@@ -0,0 +1,166 @@
using System;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using Microsoft.Win32;
namespace BCG
{
public class PersistWindowState
{
// event info that allows form to persist extra window state data
public delegate void WindowStateHandler (object sender, BlueRegistry bluereg);
public event WindowStateHandler LoadState;
public event WindowStateHandler SaveState;
private Form myParent;
private BlueRegistry myRegistry;
private int myNormalLeft;
private int myNormalTop;
private int myNormalWidth;
private int myNormalHeight;
private bool myResizable = true;
private FormWindowState myWindowState;
private bool myAllowSaveMinimized = false;
private bool mySavePosition = true;
private bool mySaveState = true;
public PersistWindowState (bool savePosition)
{
mySavePosition = savePosition;
}
public PersistWindowState ()
{
}
public bool saveState
{
[DebuggerStepThrough]
set { mySaveState = value; }
}
public Form parent
{
[DebuggerStepThrough]
get { return myParent; }
set
{
myParent = value;
myRegistry = new BlueRegistry (myParent.Text);
// subscribe to parent form's events
myParent.Closing += new System.ComponentModel.CancelEventHandler(myOnClosing);
myParent.Resize += new System.EventHandler(myOnResize);
myParent.Move += new System.EventHandler(myOnMove);
myParent.Load += new System.EventHandler(myOnLoad);
// get initial width and height in case form is never resized
myNormalWidth = myParent.Width;
myNormalHeight = myParent.Height;
}
}
public BlueRegistry blueRegistry
{
[DebuggerStepThrough]
get { return myRegistry; }
[DebuggerStepThrough]
set { myRegistry = value; }
}
public bool resizable
{
[DebuggerStepThrough]
set { myResizable = value; }
}
public bool allowSaveMinimized
{
[DebuggerStepThrough]
set { myAllowSaveMinimized = value; }
}
private void myOnResize(object sender, System.EventArgs e)
{
// save width and height
if (myParent.WindowState == FormWindowState.Normal && myResizable)
{
myNormalWidth = myParent.Width;
myNormalHeight = myParent.Height;
}
}
private void myOnMove(object sender, System.EventArgs e)
{
// save position
if(myParent.WindowState == FormWindowState.Normal)
{
myNormalLeft = myParent.Left;
myNormalTop = myParent.Top;
}
// save state
myWindowState = myParent.WindowState;
}
private void myOnClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
// save position, size and state
if (mySavePosition)
{
myRegistry.setValue (RegistryRoot.HKCU, "Left", myNormalLeft);
myRegistry.setValue (RegistryRoot.HKCU, "Top", myNormalTop);
}
if (myResizable)
{
myRegistry.setValue (RegistryRoot.HKCU, "Width", myNormalWidth);
myRegistry.setValue (RegistryRoot.HKCU, "Height", myNormalHeight);
}
// check if we are allowed to save the state as minimized (not normally)
if (!myAllowSaveMinimized)
{
if(myWindowState == FormWindowState.Minimized)
myWindowState = FormWindowState.Normal;
}
if (mySaveState)
myRegistry.setValue (RegistryRoot.HKCU, "WindowState", (int) myWindowState);
// fire SaveState event
if (SaveState != null)
SaveState (this, myRegistry);
}
private void myOnLoad (object sender, System.EventArgs e)
{
if (mySavePosition)
{
int left = (int) myRegistry.getValue (RegistryRoot.HKCU, "Left", myParent.Left);
int top = (int) myRegistry.getValue (RegistryRoot.HKCU, "Top", myParent.Top);
myParent.Location = new Point (left, top);
}
if (myResizable)
{
int width = (int) myRegistry.getValue (RegistryRoot.HKCU, "Width", myParent.Width);
int height = (int) myRegistry.getValue (RegistryRoot.HKCU, "Height", myParent.Height);
myParent.Size = new Size (width, height);
}
if (mySaveState)
{
FormWindowState windowState = (FormWindowState) myRegistry.getValue (RegistryRoot.HKCU, "WindowState",
(int) myParent.WindowState);
myParent.WindowState = windowState;
}
// fire LoadState event
if(LoadState != null)
LoadState (this, myRegistry);
}
}
}
@@ -0,0 +1,58 @@
using System;
using System.Collections;
using Microsoft.Win32;
namespace BCG
{
internal static class SortedListRegistryHandler
{
public static void setValue (RegistryKey rk, string name, SortedList slist)
{
rk.SetValue (name, slist.Count);
for (int i = 0; i < slist.Count; i++)
{
object key = slist.GetKey (i);
object val = slist.GetByIndex (i);
rk.SetValue (string.Concat (name, "_key", i.ToString ()), key);
rk.SetValue (string.Concat (name, "_val", i.ToString ()), val);
}
}
public static SortedList getValue (RegistryKey rk, string name)
{
object c = rk.GetValue (name, 0);
SortedList result = new SortedList ();
try
{
int count = (int) c;
for (int i = 0; i < count; i++)
{
object key = rk.GetValue (string.Concat (name, "_key", i.ToString ()));
object val = rk.GetValue (string.Concat (name, "_val", i.ToString ()));
result.Add (key, val);
}
}
catch (Exception)
{
result.Clear ();
}
return result;
}
public static void deleteValue (RegistryKey rk, string name)
{
object c = rk.GetValue (name, 0);
int count = (int) c;
for (int i = 0; i < count; i++)
{
rk.DeleteValue (string.Concat (name, "_key", i.ToString ()), false);
rk.DeleteValue (string.Concat (name, "_val", i.ToString ()), false);
}
rk.DeleteValue (name, false);
}
}
}
@@ -0,0 +1,21 @@
namespace Bts.BooleanExpressions.Arguments;
class Argument : IArgument {
readonly Func<IDictionary<string, object?>, object?> getValue;
public Argument(Func<IDictionary<string, object?>, object?> getValue) =>
this.getValue = getValue;
public object? GetValue(IDictionary<string, object?> env) =>
getValue(env);
}
class Argument<T> : IArgument<T> {
readonly Func<IDictionary<string, object?>, T> getValue;
public Argument(Func<IDictionary<string, object?>, T> getValue) =>
this.getValue = getValue;
public T GetValue(IDictionary<string, object?> env) =>
getValue(env);
}
@@ -0,0 +1,28 @@
namespace Bts.BooleanExpressions.Arguments;
using bts;
using Spark.Core.Collections;
static class ArgumentComparer {
public static int Compare(
IArgument value1, IArgument value2, IDictionary<string,object?> env) {
if (value1 is null) {
throw new ArgumentNullException(nameof(value1));
}
if (value2 is null) {
throw new ArgumentNullException(nameof(value2));
}
var cmp1 = value1.Cast<IComparable>();
var cmp2 = value2.Cast<IComparable>();
try {
var v1 = cmp1.GetValue(env);
var v2 = cmp2.GetValue(env);
return v1.GetType().IsNumeric() ?
new NumericComparer().Compare(v1, v2) : v1.CompareTo(v2);
} catch (Exception ex) {
Log.Ui.error($"Comparison failed: {ex}");
throw;
}
}
}
@@ -0,0 +1,11 @@
namespace Bts.BooleanExpressions.Arguments;
static class ArgumentExtensions {
public static IArgument<T> Cast<T>(this IArgument argument) =>
new Argument<T>(env => {
var obj = argument.GetValue(env);
return obj is T t ? t : throw new Exception(
$"Expected argument.GetValue to return instance of type {typeof(T)} " +
$"(actually {obj?.GetType()})");
});
}
@@ -0,0 +1,19 @@
namespace Bts.BooleanExpressions.Arguments;
using System.Text.RegularExpressions;
static class ArgumentMatcher {
public static bool Match(
IArgument arg1, IArgument arg2, IDictionary<string, object?> env) {
var lobj = arg1.GetValue(env);
var robj = arg2.GetValue(env);
if (DBNull.Value.Equals(lobj) && robj is string) {
return false;
}
if (lobj is string lstr && robj is string rstr) {
return Regex.IsMatch(lstr, rstr);
}
throw new Exception(
$"Type mismatch, cannot string match {lobj?.GetType()} with {robj?.GetType()}");
}
}
@@ -0,0 +1,16 @@
namespace Bts.BooleanExpressions.Arguments;
static class Constant {
public static Constant<T> Create<T>(T value) =>
new(value);
}
class Constant<T> : IArgument<T> {
readonly T value;
public Constant(T value) =>
this.value = value;
public T GetValue(IDictionary<string, object?> env) =>
value;
}
@@ -0,0 +1,29 @@
namespace Bts.BooleanExpressions.Arguments;
class Function : IArgument {
public const string FunctionPrefix = "function:";
readonly string name;
readonly IEnumerable<IArgument> args;
public Function(string name, IEnumerable<IArgument>? args = null) {
this.name = name;
this.args = args ?? Enumerable.Empty<IArgument>();
}
public delegate object? Delegate(List<object?> args);
public object? GetValue(IDictionary<string, object?> env) {
var argValues = args?.Select(a => a.GetValue(env))?.ToList() ?? new(0);
var k = FunctionPrefix + name;
if (!env.TryGetValue(k, out var fnObj)) {
throw new BooleanExpressionException($"Did not find function named '{name}'");
}
if (fnObj is not Delegate fn) {
throw new BooleanExpressionException(
$"Function {name} is not of type {typeof(Delegate)}");
}
return fn(argValues);
}
}
@@ -0,0 +1,12 @@
namespace Bts.BooleanExpressions;
interface IArgument {
object? GetValue(IDictionary<string, object?> env);
}
interface IArgument<T> : IArgument {
new T GetValue(IDictionary<string, object?> env);
object? IArgument.GetValue(IDictionary<string, object?> env) =>
GetValue(env);
}
@@ -0,0 +1,12 @@
namespace Bts.BooleanExpressions.Arguments;
class Variable : IArgument {
readonly string name;
public Variable(string name) =>
this.name = name;
public object? GetValue(IDictionary<string, object?> env) =>
env.TryGetValue(name, out var res) ?
res : throw new BooleanExpressionException($"Did not find variable named '{name}'");
}
@@ -0,0 +1,13 @@
namespace Bts.BooleanExpressions;
class BinaryOperator : IBinaryOperator {
readonly Func<IArgument?, IArgument?, IDictionary<string, object?>, bool> op;
public BinaryOperator(
Func<IArgument?, IArgument?, IDictionary<string, object?>, bool> op) =>
this.op = op;
public bool Evaluate(
IArgument? arg1, IArgument? arg2, IDictionary<string, object?> bindings) =>
op(arg1, arg2, bindings);
}
@@ -0,0 +1,19 @@
namespace Bts.BooleanExpressions;
using bts;
class BooleanExpression : IBooleanExpression {
readonly Func<IDictionary<string, object?>, bool> evaluate;
public BooleanExpression(Func<IDictionary<string, object?>, bool> evaluate) =>
this.evaluate = evaluate;
public bool Evaluate(IDictionary<string, object?> env) {
try {
return evaluate(env);
} catch (Exception ex) {
Log.assert(false, $"BooleanExpression.Evaluate failed: {ex}");
throw;
}
}
}
@@ -0,0 +1,6 @@
namespace Bts.BooleanExpressions;
public class BooleanExpressionException : Exception {
public BooleanExpressionException(string format, params object[] args)
: base(string.Format(format, args)) { }
}
@@ -0,0 +1,176 @@
%namespace Bts.BooleanExpressions
%partial
%visibility internal
%tokentype Token
%parsertype BooleanExpressionParserImpl
%union {
public int Integer;
public double Real;
public bool Boolean;
public string String;
public string Identifier;
public DateTime DateTime;
public ImmutableList<Definition> Definitions;
public Definition Definition;
public ImmutableList<string> Parameters;
public ImmutableList<IArgument> Arguments;
public IArgument Argument;
public BooleanExpression Expression;
public BoundBooleanExpression BoundExpression;
}
/* Constants */
%token BOOLEAN_CONSTANT, INTEGER_CONSTANT, STRING_CONSTANT, NULL_CONSTANT, DATE_TIME_CONSTANT, REAL_CONSTANT
/* Logical Operators */
%token OR, AND, XOR, NOT
/* Syntax */
%token PARENTHESIS_OPEN, PARENTHESIS_CLOSE, COMMA, IDENTIFIER, DEFINE, BEGIN_DEF, END_DEF
/* Relational */
%token EQUAL, LESS_EQUAL, GREATER_EQUAL, LESS, GREATER, DIFFERENT, DIFFERENT2, MATCHES
%left OR AND XOR
%right NOT
%nonassoc EQUAL
%type <BoundExpression> BoundExpression
%type <Definitions> Definitions
%type <Definition> Definition
%type <Expression> Expression
%type <Parameters> Parameters
%type <Arguments> Arguments
%type <Argument> Argument
%%
BoundExpression : Definitions Expression { $$ = new($2, $1); }
| Expression { $$ = new($1, ImmutableList<Definition>.Empty); };
Definitions :
Definition { $$ = ImmutableList<Definition>.Empty.Add($1); }
| Definitions Definition { $$ = $1.Add($2); };
Definition :
DEFINE IDENTIFIER PARENTHESIS_OPEN Parameters PARENTHESIS_CLOSE BEGIN_DEF Expression END_DEF {
$$ = new($2.Identifier, $4, $7);
};
Expression :
Expression OR Expression {
var left = $1;
var right = $3;
$$ = new(env => left.Evaluate(env) || right.Evaluate(env));
}
| Expression AND Expression {
var left = $1;
var right = $3;
$$ = new(env => left.Evaluate(env) && right.Evaluate(env));
}
| Expression XOR Expression {
var left = $1;
var right = $3;
$$ = new(env => left.Evaluate(env) != right.Evaluate(env));
}
| NOT Expression {
var exp = $2;
$$ = new(env => !exp.Evaluate(env));
}
| PARENTHESIS_OPEN Expression PARENTHESIS_CLOSE {
$$ = $2;
}
| Argument GREATER Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) > 0);
}
| Argument GREATER_EQUAL Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) >= 0);
}
| Argument EQUAL Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) == 0);
}
| Argument LESS_EQUAL Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) <= 0);
}
| Argument LESS Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) < 0);
}
| Argument DIFFERENT Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) != 0);
}
| Argument DIFFERENT2 Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) != 0);
}
| Argument MATCHES Argument {
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentMatcher.Match(left, right, env));
}
| Argument {
var arg = $1;
$$ = new(env => (bool)arg.GetValue(env));
}
;
Parameters :
{
$$ = ImmutableList<string>.Empty;
}
| IDENTIFIER {
$$ = ImmutableList<string>.Empty.Add($1.Identifier);
}
| IDENTIFIER COMMA Parameters {
$$ = $3.Insert(0, $1.Identifier);
}
;
Arguments :
{
$$ = ImmutableList<IArgument>.Empty;
}
| Argument {
$$ = ImmutableList<IArgument>.Empty.Add($1);
}
| Arguments COMMA Argument {
$$ = $1.Add($3);
}
;
Argument : IDENTIFIER
{
$$ = new Arguments.Variable($1.Identifier);
}
| BOOLEAN_CONSTANT {
$$ = Arguments.Constant.Create($1.Boolean);
}
| NULL_CONSTANT {
$$ = Arguments.Constant.Create(DBNull.Value);
}
| REAL_CONSTANT {
$$ = Arguments.Constant.Create($1.Real);
}
| STRING_CONSTANT {
$$ = Arguments.Constant.Create($1.String);
}
| INTEGER_CONSTANT {
$$ = Arguments.Constant.Create($1.Integer);
}
| DATE_TIME_CONSTANT {
$$ = Arguments.Constant.Create($1.DateTime);
}
| IDENTIFIER PARENTHESIS_OPEN Arguments PARENTHESIS_CLOSE {
$$ = new Arguments.Function($1.Identifier, $3);
}
;
@@ -0,0 +1,6 @@
namespace Bts.BooleanExpressions;
public class BooleanExpressionInterpreterException : System.Exception {
public BooleanExpressionInterpreterException(string message)
: base(message) { }
}
@@ -0,0 +1,16 @@
namespace Bts.BooleanExpressions;
using Bts.ExpressionCore;
public static class BooleanExpressionParser {
public static IBooleanExpression Parse(Stream expression) =>
new Parser().Parse(expression);
public static IBooleanExpression Parse(string expression) =>
new Parser().Parse(expression);
class Parser : IParser<IBooleanExpression> {
public IBooleanExpression Parse(Stream expression) =>
new BooleanExpressionParserImpl().Parse(expression).BoundExpression;
}
}
@@ -0,0 +1,22 @@
namespace Bts.BooleanExpressions;
using QUT.Gppg;
using System.IO;
using System.Text;
partial class BooleanExpressionParserImpl {
public BooleanExpressionParserImpl(AbstractScanner<ValueType, LexLocation>? scanner = null)
: base(scanner) { }
public ValueType Parse(string s) {
using var ms = new MemoryStream(Encoding.Default.GetBytes(s));
return Parse(ms);
}
public ValueType Parse(Stream stream) {
Scanner = new BooleanExpressionScanner(stream);
Parse();
return CurrentSemanticValue;
}
}
@@ -0,0 +1,13 @@
namespace Bts.BooleanExpressions;
using System;
partial class BooleanExpressionScanner {
bts.Logger Logger => bts.Log.Gen;
public override void yyerror(string format, params object[] args) {
base.yyerror(format, args);
Console.WriteLine(format, args);
Console.WriteLine();
}
}
@@ -0,0 +1,174 @@
%namespace Bts.BooleanExpressions
%scannertype BooleanExpressionScanner
%visibility internal
%tokentype Token
%option stack, minimize, parser, verbose, persistbuffer, noembedbuffers
/* Literal Constants */
Letter [a-zA-Z]
BooleanConstant 'true'|'false'
CSStringConstant \"([^\"\\]*|\\.)*\"
DateTimeConstant ([1-9]|'10'|'11'|'12')\/([1-9]|([1-2][0-9])|'30'|'31')\/[0-9][0-9][0-9]*
IntegerConstant -?[0-9]+
NullConstant 'null'
RealConstant -?[0-9]+\.[0-9]+
StringConstant \'([^\'\\]*|\\.)*\'
/* Relational Operators */
Equal =
LessEqual <=
GreaterEqual >=
Less <
Greater >
Different !=
Different2 <>
Matches ~=
/* Logical Operators */
Or or
And and
Not not
Xor xor
Define define
BeginDef \{
EndDef \}
Identifier {Letter}({Letter}*[0-9]*_*)*
/* Utility Tokens */
OpenParenthesis \(
CloseParenthesis \)
Comma ,
Negate '!'
MapsTo ':'
IsOfType '/'
%%
{StringConstant} {
yylval.String = yytext.Substring(1, yytext.Length - 2).Replace(@"\'", "'");
return (int)Token.STRING_CONSTANT;
}
{BooleanConstant} {
yylval.Boolean = yytext.ToLower() switch {
"true" => true,
"false" => false,
_ => throw new Exception(
string.Format("Expected yytext to be 'true' or 'false' (actually '{0}')", yytext))
};
return (int)Token.BOOLEAN_CONSTANT;
}
{NullConstant} {
yylval.Null = DBNull.Value;
return (int)Token.NULL_CONSTANT;
}
{DateTimeConstant} {
yylval.DateTime = DateTime.Parse(yytext);
return (int)Token.DATE_TIME_CONSTANT;
}
{IntegerConstant} {
yylval.Integer = int.Parse(yytext);
return (int)Token.INTEGER_CONSTANT;
}
{RealConstant} {
yylval.Real = double.Parse(yytext);
return (int)Token.REAL_CONSTANT;
}
{OpenParenthesis} {
return (int)Token.PARENTHESIS_OPEN;
}
{CloseParenthesis} {
return (int)Token.PARENTHESIS_CLOSE;
}
{Comma} {
return (int)Token.COMMA;
}
{Negate} {
return (int)Token.NEGATE;
}
{MapsTo} {
return (int)Token.MAPS_TO;
}
{Equal} {
return (int)Token.EQUAL;
}
{LessEqual} {
return (int)Token.LESS_EQUAL;
}
{GreaterEqual} {
return (int)Token.GREATER_EQUAL;
}
{Less} {
return (int)Token.LESS;
}
{Greater} {
return (int)Token.GREATER;
}
{Different} {
return (int)Token.DIFFERENT;
}
{Different2} {
return (int)Token.DIFFERENT2;
}
{Matches} {
return (int)Token.MATCHES;
}
{Or} {
return (int)Token.OR;
}
{And} {
return (int)Token.AND;
}
{Not} {
return (int)Token.NOT;
}
{Xor} {
return (int)Token.XOR;
}
{IsOfType} {
return (int)Token.IS_OF_TYPE;
}
{Define} {
return (int)Token.DEFINE;
}
{BeginDef} {
return (int)Token.BEGIN_DEF;
}
{EndDef} {
return (int)Token.END_DEF;
}
{Identifier} {
yylval.Identifier = yytext;
return (int)Token.IDENTIFIER;
}
%%
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.24.3" />
<PackageReference Include="YaccLexTools" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ExpressionCore\ExpressionCore.csproj" />
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
</ItemGroup>
<ItemGroup>
<Scanner Include="BooleanExpressionTokens.lex" />
<Parser Include="BooleanExpressionGrammar.y" />
</ItemGroup>
</Project>
@@ -0,0 +1,32 @@
namespace Bts.BooleanExpressions;
using Bts.BooleanExpressions.Arguments;
class BoundBooleanExpression : IBooleanExpression {
readonly IBooleanExpression expression;
readonly IDictionary<string, FunctionDefinition> definitions;
readonly Dictionary<string, object?> identifiers;
public BoundBooleanExpression(
IBooleanExpression expression, IEnumerable<Definition>? definitions = null) {
this.expression = expression;
var defs = definitions ?? Enumerable.Empty<Definition>();
identifiers = defs.ToDictionary(
kv => kv.id, kv => (object?)kv.exp);
this.definitions = extractFunctions(defs).ToDictionary(kv => kv.Key, kv => kv.Value);
}
public bool Evaluate(IDictionary<string, object?> env) {
foreach (var kv in env) {
identifiers[kv.Key] = kv.Value;
}
env = new EvaluationEnvironment(identifiers, definitions);
return expression.Evaluate(env);
}
static IEnumerable<KeyValuePair<string, FunctionDefinition>> extractFunctions(
IEnumerable<Definition> definitions) =>
definitions.Select(d =>
new KeyValuePair<string, FunctionDefinition>(
Function.FunctionPrefix + d.id, new(d.id, d.args.ToList(), d.exp)));
}
@@ -0,0 +1,18 @@
namespace Bts.BooleanExpressions;
using System.Collections.Immutable;
public class Definition {
public Definition(string id, ImmutableList<string> args, IBooleanExpression exp) {
this.id = id;
this.args = args;
this.exp = exp;
}
public string id { get; }
public ImmutableList<string> args { get; }
public IBooleanExpression exp { get; }
public override string ToString() =>
$"{id}({string.Join(", ", args)} | {exp?.GetType()})";
}
@@ -0,0 +1,123 @@
namespace Bts.BooleanExpressions;
using Bts.BooleanExpressions.Arguments;
using Spark.Core.Collections;
using System.Collections;
class EvaluationEnvironment : IDictionary<string, object?> {
IDictionary<string, object?> userBindings;
IDictionary<string, FunctionDefinition> definitions;
public EvaluationEnvironment(
IDictionary<string, object?> userBindings,
IDictionary<string, FunctionDefinition> definitions) {
this.userBindings = userBindings;
this.definitions = definitions;
}
public int Count =>
definitions.Count + userBindings.Count;
public bool IsReadOnly => true;
public ICollection<string> Keys =>
AggregateCollection.Create(userBindings.Keys, definitions.Keys);
public ICollection<object?> Values =>
AggregateCollection.Create(
userBindings.Values, SelectorCollection.Create(definitions.Values, v => (object?)v));
public object? this[string key] {
get {
var keystr = key.ToString();
if (keystr is null || !definitions.TryGetValue(keystr, out var fd)) {
return userBindings.TryGetValue(key, out var ubnd) ? ubnd :
throw new KeyNotFoundException(
$"EvaluationEnvironment does not contain key '{key}'");
}
return new Function.Delegate(Evaluate);
object? Evaluate(List<object?> args) {
if (args.Count != fd.args.Count)
throw new BooleanExpressionInterpreterException(
$"Parameter count mismatch for {fd.name}. Expected: {fd.args} Got: {args.Count}");
else {
var newBindings = fd.args.Zip(args).ToDictionary();
return fd.expression.Evaluate(new EvaluationEnvironment(
AggregateDictionary.Create(newBindings, userBindings), definitions));
}
}
}
set => throw new NotSupportedException();
}
public bool ContainsKey(string key) {
var keystr = key.ToString();
return
(keystr is not null && definitions.ContainsKey(keystr)) ||
userBindings.ContainsKey(key);
}
public IEnumerator<KeyValuePair<string, object?>> GetEnumerator() {
foreach (var kv in userBindings) {
yield return kv;
}
foreach (var kv in definitions) {
if (!userBindings.ContainsKey(kv.Key)) {
yield return new(kv.Key, kv.Value);
}
}
}
public bool TryGetValue(string key, out object? value) {
var keystr = key.ToString();
if (keystr is null || !definitions.TryGetValue(keystr, out var fd)) {
return userBindings.TryGetValue(key, out value);
}
value = new Function.Delegate(Evaluate);
return true;
object? Evaluate(List<object?> args) {
if (args.Count != fd.args.Count)
throw new BooleanExpressionInterpreterException(
$"Parameter count mismatch for {fd.name}. Expected: {fd.args} Got: {args.Count}");
else {
var newBindings = fd.args.Zip(args).ToDictionary();
return fd.expression.Evaluate(new EvaluationEnvironment(
AggregateDictionary.Create(newBindings, userBindings), definitions));
}
}
}
public void CopyTo(KeyValuePair<string, object?>[] array, int arrayIndex) {
foreach (var kv in userBindings) {
array[arrayIndex++] = kv;
}
foreach (var kv in definitions) {
array[arrayIndex++] = new(kv.Key, kv.Value);
}
}
void IDictionary<string, object?>.Add(string key, object? value) =>
throw new NotSupportedException();
void ICollection<KeyValuePair<string, object?>>.Add(KeyValuePair<string, object?> item) =>
throw new NotSupportedException();
void ICollection<KeyValuePair<string, object?>>.Clear() =>
throw new NotSupportedException();
bool ICollection<KeyValuePair<string, object?>>.Contains(KeyValuePair<string, object?> item) =>
TryGetValue(item.Key, out var v) && Equals(v, item.Value);
IEnumerator IEnumerable.GetEnumerator() =>
GetEnumerator();
bool IDictionary<string, object?>.Remove(string key) =>
throw new NotSupportedException();
bool ICollection<KeyValuePair<string, object?>>.Remove(KeyValuePair<string, object?> item) =>
throw new NotSupportedException();
}
@@ -0,0 +1,14 @@
namespace Bts.BooleanExpressions;
class FunctionDefinition {
public FunctionDefinition(
string name, IList<string> args, IBooleanExpression expression) {
this.name = name;
this.args = args;
this.expression = expression;
}
public string name { get; }
public IList<string> args { get; }
public IBooleanExpression expression { get; }
}
@@ -0,0 +1,720 @@
// ==============================================================
// <auto-generated>
// This code automatically produced from an embedded resource.
// Do not edit this file, or it will become incompatible with
// the specification from which it was generated.
// </auto-generated>
// ==============================================================
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using System.Globalization;
namespace QUT.GplexBuffers
{
// Code copied from GPLEX embedded resource
[Serializable]
internal class BufferException : Exception
{
public BufferException() { }
public BufferException(string message) : base(message) { }
public BufferException(string message, Exception innerException)
: base(message, innerException) { }
protected BufferException(SerializationInfo info, StreamingContext context)
: base(info, context) { }
}
internal abstract class ScanBuff
{
private string fileNm;
public const int EndOfFile = -1;
public const int UnicodeReplacementChar = 0xFFFD;
public bool IsFile { get { return (fileNm != null); } }
public string FileName { get { return fileNm; } set { fileNm = value; } }
public abstract int Pos { get; set; }
public abstract int Read();
public virtual void Mark() { }
public abstract string GetString(int begin, int limit);
public static ScanBuff GetBuffer(string source)
{
return new StringBuffer(source);
}
public static ScanBuff GetBuffer(IList<string> source)
{
return new LineBuffer(source);
}
#if (!NOFILES)
public static ScanBuff GetBuffer(Stream source)
{
return new BuildBuffer(source);
}
#if (!BYTEMODE)
public static ScanBuff GetBuffer(Stream source, int fallbackCodePage)
{
return new BuildBuffer(source, fallbackCodePage);
}
#endif // !BYTEMODE
#endif // !NOFILES
}
#region Buffer classes
// ==============================================================
// ===== Definitions for various ScanBuff derived classes ====
// ==============================================================
// =============== String input ================
// ==============================================================
/// <summary>
/// This class reads characters from a single string as
/// required, for example, by Visual Studio language services
/// </summary>
sealed class StringBuffer : ScanBuff
{
string str; // input buffer
int bPos; // current position in buffer
int sLen;
public StringBuffer(string source)
{
this.str = source;
this.sLen = source.Length;
this.FileName = null;
}
public override int Read()
{
if (bPos < sLen) return str[bPos++];
else if (bPos == sLen) { bPos++; return '\n'; } // one strike, see new line
else { bPos++; return EndOfFile; } // two strikes and you're out!
}
public override string GetString(int begin, int limit)
{
// "limit" can be greater than sLen with the BABEL
// option set. Read returns a "virtual" EOL if
// an attempt is made to read past the end of the
// string buffer. Without the guard any attempt
// to fetch yytext for a token that includes the
// EOL will throw an index exception.
if (limit > sLen) limit = sLen;
if (limit <= begin) return "";
else return str.Substring(begin, limit - begin);
}
public override int Pos
{
get { return bPos; }
set { bPos = value; }
}
public override string ToString() { return "StringBuffer"; }
}
// ==============================================================
// The LineBuff class contributed by Nigel Horspool,
// nigelh@cs.uvic.cs
// ==============================================================
sealed class LineBuffer : ScanBuff
{
IList<string> line; // list of source lines from a file
int numLines; // number of strings in line list
string curLine; // current line in that list
int cLine; // index of current line in the list
int curLen; // length of current line
int curLineStart; // position of line start in whole file
int curLineEnd; // position of line end in whole file
int maxPos; // max position ever visited in whole file
int cPos; // ordinal number of code in source
// Constructed from a list of strings, one per source line.
// The lines have had trailing '\n' characters removed.
public LineBuffer(IList<string> lineList)
{
line = lineList;
numLines = line.Count;
cPos = curLineStart = 0;
curLine = (numLines > 0 ? line[0] : "");
maxPos = curLineEnd = curLen = curLine.Length;
cLine = 1;
FileName = null;
}
public override int Read()
{
if (cPos < curLineEnd)
return curLine[cPos++ - curLineStart];
if (cPos++ == curLineEnd)
return '\n';
if (cLine >= numLines)
return EndOfFile;
curLine = line[cLine];
curLen = curLine.Length;
curLineStart = curLineEnd + 1;
curLineEnd = curLineStart + curLen;
if (curLineEnd > maxPos)
maxPos = curLineEnd;
cLine++;
return curLen > 0 ? curLine[0] : '\n';
}
// To speed up searches for the line containing a position
private int cachedPosition;
private int cachedIxdex;
private int cachedLineStart;
// Given a position pos within the entire source, the results are
// ix -- the index of the containing line
// lstart -- the position of the first character on that line
private void findIndex(int pos, out int ix, out int lstart)
{
if (pos >= cachedPosition)
{
ix = cachedIxdex; lstart = cachedLineStart;
}
else
{
ix = lstart = 0;
}
while (ix < numLines)
{
int len = line[ix].Length + 1;
if (pos < lstart + len) break;
lstart += len;
ix++;
}
cachedPosition = pos;
cachedIxdex = ix;
cachedLineStart = lstart;
}
public override string GetString(int begin, int limit)
{
if (begin >= maxPos || limit <= begin) return "";
int endIx, begIx, endLineStart, begLineStart;
findIndex(begin, out begIx, out begLineStart);
int begCol = begin - begLineStart;
findIndex(limit, out endIx, out endLineStart);
int endCol = limit - endLineStart;
string s = line[begIx];
if (begIx == endIx)
{
// the usual case, substring all on one line
return (endCol <= s.Length) ?
s.Substring(begCol, endCol - begCol)
: s.Substring(begCol) + "\n";
}
// the string spans multiple lines, yuk!
StringBuilder sb = new StringBuilder();
if (begCol < s.Length)
sb.Append(s.Substring(begCol));
for (; ; )
{
sb.Append("\n");
s = line[++begIx];
if (begIx >= endIx) break;
sb.Append(s);
}
if (endCol <= s.Length)
{
sb.Append(s.Substring(0, endCol));
}
else
{
sb.Append(s);
sb.Append("\n");
}
return sb.ToString();
}
public override int Pos
{
get { return cPos; }
set
{
cPos = value;
findIndex(cPos, out cLine, out curLineStart);
// cLine should be the *next* line after curLine.
curLine = (cLine < numLines ? line[cLine++] : "");
curLineEnd = curLineStart + curLine.Length;
}
}
public override string ToString() { return "LineBuffer"; }
}
#if (!NOFILES)
// ==============================================================
// ===== class BuildBuff : for unicode text files ========
// ==============================================================
class BuildBuffer : ScanBuff
{
// Double buffer for char stream.
class BufferElement
{
StringBuilder bldr = new StringBuilder();
StringBuilder next = new StringBuilder();
int minIx;
int maxIx;
int brkIx;
bool appendToNext;
internal BufferElement() { }
internal int MaxIndex { get { return maxIx; } }
// internal int MinIndex { get { return minIx; } }
internal char this[int index]
{
get
{
if (index < minIx || index >= maxIx)
throw new BufferException("Index was outside data buffer");
else if (index < brkIx)
return bldr[index - minIx];
else
return next[index - brkIx];
}
}
internal void Append(char[] block, int count)
{
maxIx += count;
if (appendToNext)
this.next.Append(block, 0, count);
else
{
this.bldr.Append(block, 0, count);
brkIx = maxIx;
appendToNext = true;
}
}
internal string GetString(int start, int limit)
{
if (limit <= start)
return "";
if (start >= minIx && limit <= maxIx)
if (limit < brkIx) // String entirely in bldr builder
return bldr.ToString(start - minIx, limit - start);
else if (start >= brkIx) // String entirely in next builder
return next.ToString(start - brkIx, limit - start);
else // Must do a string-concatenation
return
bldr.ToString(start - minIx, brkIx - start) +
next.ToString(0, limit - brkIx);
else
throw new BufferException("String was outside data buffer");
}
internal void Mark(int limit)
{
if (limit > brkIx + 16) // Rotate blocks
{
StringBuilder temp = bldr;
bldr = next;
next = temp;
next.Length = 0;
minIx = brkIx;
brkIx = maxIx;
}
}
}
BufferElement data = new BufferElement();
int bPos; // Postion index in the StringBuilder
BlockReader NextBlk; // Delegate that serves char-arrays;
private string EncodingName
{
get
{
StreamReader rdr = NextBlk.Target as StreamReader;
return (rdr == null ? "raw-bytes" : rdr.CurrentEncoding.BodyName);
}
}
public BuildBuffer(Stream stream)
{
FileStream fStrm = (stream as FileStream);
if (fStrm != null) FileName = fStrm.Name;
NextBlk = BlockReaderFactory.Raw(stream);
}
#if (!BYTEMODE)
public BuildBuffer(Stream stream, int fallbackCodePage)
{
FileStream fStrm = (stream as FileStream);
if (fStrm != null) FileName = fStrm.Name;
NextBlk = BlockReaderFactory.Get(stream, fallbackCodePage);
}
#endif
/// <summary>
/// Marks a conservative lower bound for the buffer,
/// allowing space to be reclaimed. If an application
/// needs to call GetString at arbitrary past locations
/// in the input stream, Mark() is not called.
/// </summary>
public override void Mark() { data.Mark(bPos - 2); }
public override int Pos
{
get { return bPos; }
set { bPos = value; }
}
/// <summary>
/// Read returns the ordinal number of the next char, or
/// EOF (-1) for an end of stream. Note that the next
/// code point may require *two* calls of Read().
/// </summary>
/// <returns></returns>
public override int Read()
{
//
// Characters at positions
// [data.offset, data.offset + data.bldr.Length)
// are available in data.bldr.
//
if (bPos < data.MaxIndex)
{
// ch0 cannot be EOF
return (int)data[bPos++];
}
else // Read from underlying stream
{
// Experimental code, blocks of page size
char[] chrs = new char[4096];
int count = NextBlk(chrs, 0, 4096);
if (count == 0)
return EndOfFile;
else
{
data.Append(chrs, count);
return (int)data[bPos++];
}
}
}
public override string GetString(int begin, int limit)
{
return data.GetString(begin, limit);
}
public override string ToString()
{
return "StringBuilder buffer, encoding: " + this.EncodingName;
}
}
// =============== End ScanBuff-derived classes ==================
internal delegate int BlockReader(char[] block, int index, int number);
// A delegate factory, serving up a delegate that
// reads a block of characters from the underlying
// encoded stream, via a StreamReader object.
//
internal static class BlockReaderFactory
{
public static BlockReader Raw(Stream stream)
{
return delegate(char[] block, int index, int number)
{
byte[] b = new byte[number];
int count = stream.Read(b, 0, number);
int i = 0;
int j = index;
for (; i < count; i++, j++)
block[j] = (char)b[i];
return count;
};
}
#if (!BYTEMODE)
public static BlockReader Get(Stream stream, int fallbackCodePage)
{
Encoding encoding;
int preamble = Preamble(stream);
if (preamble != 0) // There is a valid BOM here!
encoding = Encoding.GetEncoding(preamble);
else if (fallbackCodePage == -1) // Fallback is "raw" bytes
return Raw(stream);
else if (fallbackCodePage != -2) // Anything but "guess"
encoding = Encoding.GetEncoding(fallbackCodePage);
else // This is the "guess" option
{
int guess = new Guesser(stream).GuessCodePage();
stream.Seek(0, SeekOrigin.Begin);
if (guess == -1) // ==> this is a 7-bit file
encoding = Encoding.ASCII;
else if (guess == 65001)
encoding = Encoding.UTF8;
else // ==> use the machine default
encoding = Encoding.Default;
}
StreamReader reader = new StreamReader(stream, encoding);
return reader.Read;
}
static int Preamble(Stream stream)
{
int b0 = stream.ReadByte();
int b1 = stream.ReadByte();
if (b0 == 0xfe && b1 == 0xff)
return 1201; // UTF16BE
if (b0 == 0xff && b1 == 0xfe)
return 1200; // UTF16LE
int b2 = stream.ReadByte();
if (b0 == 0xef && b1 == 0xbb && b2 == 0xbf)
return 65001; // UTF8
//
// There is no unicode preamble, so we
// return denoter for the machine default.
//
stream.Seek(0, SeekOrigin.Begin);
return 0;
}
#endif // !BYTEMODE
}
#endif // !NOFILES
#endregion Buffer classes
// ==============================================================
// ============ class CodePageHandling =============
// ==============================================================
#if (!NOFILES)
public static class CodePageHandling
{
public static int GetCodePage(string option)
{
string command = option.ToUpperInvariant();
if (command.StartsWith("CodePage:", StringComparison.OrdinalIgnoreCase))
command = command.Substring(9);
try
{
if (command.Equals("RAW"))
return -1;
else if (command.Equals("GUESS"))
return -2;
else if (command.Equals("DEFAULT"))
return 0;
else if (char.IsDigit(command[0]))
return int.Parse(command, CultureInfo.InvariantCulture);
else
{
Encoding enc = Encoding.GetEncoding(command);
return enc.CodePage;
}
}
catch (FormatException)
{
Console.Error.WriteLine(
"Invalid format \"{0}\", using machine default", option);
}
catch (ArgumentException)
{
Console.Error.WriteLine(
"Unknown code page \"{0}\", using machine default", option);
}
return 0;
}
}
#region guesser
#if (!BYTEMODE)
// ==============================================================
// ============ Encoding Guesser =============
// ==============================================================
/// <summary>
/// This class provides a simple finite state automaton that
/// scans the file looking for (1) valid UTF-8 byte patterns,
/// (2) bytes >= 0x80 which are not part of a UTF-8 sequence.
/// The method then guesses whether it is UTF-8 or maybe some
/// local machine default encoding. This works well for the
/// various Latin encodings.
/// </summary>
internal class Guesser
{
ScanBuff buffer;
public int GuessCodePage() { return Scan(); }
const int maxAccept = 10;
const int initial = 0;
const int eofNum = 0;
const int goStart = -1;
const int INITIAL = 0;
const int EndToken = 0;
#region user code
/*
* Reads the bytes of a file to determine if it is
* UTF-8 or a single-byte code page file.
*/
public long utfX;
public long uppr;
#endregion user code
int state;
int currentStart = startState[0];
int code;
#region ScannerTables
static int[] startState = new int[] { 11, 0 };
#region CharacterMap
static sbyte[] map = new sbyte[256] {
/* '\0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '\x10' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '\x20' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '0' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '@' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 'P' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '`' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 'p' */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* '\x80' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\x90' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\xA0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\xB0' */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* '\xC0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* '\xD0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* '\xE0' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
/* '\xF0' */ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 };
#endregion
static sbyte[][] nextState = new sbyte[][] {
new sbyte[] {0, 0, 0, 0, 0, 0},
new sbyte[] {-1, -1, 10, -1, -1, -1},
new sbyte[] {-1, -1, -1, -1, -1, -1},
new sbyte[] {-1, -1, 8, -1, -1, -1},
new sbyte[] {-1, -1, 5, -1, -1, -1},
new sbyte[] {-1, -1, 6, -1, -1, -1},
new sbyte[] {-1, -1, 7, -1, -1, -1},
null,
new sbyte[] {-1, -1, 9, -1, -1, -1},
null,
null,
new sbyte[] {-1, 1, 2, 3, 4, 2}
};
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
// Reason for suppression: cannot have self-reference in array initializer.
static Guesser()
{
nextState[7] = nextState[2];
nextState[9] = nextState[2];
nextState[10] = nextState[2];
}
int NextState()
{
if (code == ScanBuff.EndOfFile)
return eofNum;
else
return nextState[state][map[code]];
}
#endregion
public Guesser(System.IO.Stream file) { SetSource(file); }
public void SetSource(System.IO.Stream source)
{
this.buffer = new BuildBuffer(source);
code = buffer.Read();
}
int Scan()
{
for (; ; )
{
int next;
state = currentStart;
while ((next = NextState()) == goStart)
code = buffer.Read();
state = next;
code = buffer.Read();
while ((next = NextState()) > eofNum)
{
state = next;
code = buffer.Read();
}
if (state <= maxAccept)
{
#region ActionSwitch
#pragma warning disable 162
switch (state)
{
case eofNum:
switch (currentStart)
{
case 11:
if (utfX == 0 && uppr == 0) return -1; /* raw ascii */
else if (uppr * 10 > utfX) return 0; /* default code page */
else return 65001; /* UTF-8 encoding */
break;
}
return EndToken;
case 1: // Recognized '{Upper128}', Shortest string "\xC0"
case 2: // Recognized '{Upper128}', Shortest string "\x80"
case 3: // Recognized '{Upper128}', Shortest string "\xE0"
case 4: // Recognized '{Upper128}', Shortest string "\xF0"
uppr++;
break;
case 5: // Recognized '{Utf8pfx4}{Utf8cont}', Shortest string "\xF0\x80"
uppr += 2;
break;
case 6: // Recognized '{Utf8pfx4}{Utf8cont}{2}', Shortest string "\xF0\x80\x80"
uppr += 3;
break;
case 7: // Recognized '{Utf8pfx4}{Utf8cont}{3}', Shortest string "\xF0\x80\x80\x80"
utfX += 3;
break;
case 8: // Recognized '{Utf8pfx3}{Utf8cont}', Shortest string "\xE0\x80"
uppr += 2;
break;
case 9: // Recognized '{Utf8pfx3}{Utf8cont}{2}', Shortest string "\xE0\x80\x80"
utfX += 2;
break;
case 10: // Recognized '{Utf8pfx2}{Utf8cont}', Shortest string "\xC0\x80"
utfX++;
break;
default:
break;
}
#pragma warning restore 162
#endregion
}
}
}
} // end class Guesser
#endif // !BYTEMODE
#endregion
#endif // !NOFILES
// End of code copied from embedded resource
}
@@ -0,0 +1,5 @@
namespace Bts.BooleanExpressions;
interface IBinaryOperator {
bool Evaluate(IArgument? left, IArgument? right, IDictionary<string, object?> env);
}
@@ -0,0 +1,5 @@
namespace Bts.BooleanExpressions;
public interface IBooleanExpression {
bool Evaluate(IDictionary<string, object?> env);
}
Loaded 100 of 3000 files, more files were not shown because too many files have changed in this diff. Show more