diff --git a/CHANGELOG.md b/CHANGELOG.md index 44db12f..23985d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.34.0 - 2025-04-22 + +### Enhancements +- Added `SystemCode` and `ErrorCode` enums to indicate types of system and error + messages +- Converting a `v1::SystemMsg` to a `v2::SystemMsg` now sets to `code` to the heartbeat + value +- Introduced `kAssetCstrLen` constant containing the size of `asset` field in + `InstrumentDefMsg` + +### Breaking changes +- Increased the size of `asset` field in `v3::InstrumentDefMsg` from 7 to 11. The + `v3::InstrumentDefMsg` message size remains 520 bytes. +- Set minimum CMake version to 3.24 +- Changed type of `code` field in `SystemMsg` to `SystemCode` +- Changed type of `code` field in `ErrorMsg` to `ErrorCode` + +### Bug fixes +- Changed `TriState` to a regular enum to handle unexpected values +- Fixed `ccache` support +- Changed to explicitly only support being built as a static library + ## 0.33.0 - 2025-04-15 ### Enhancements diff --git a/CMakeLists.txt b/CMakeLists.txt index e91eccb..3c5c32d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,15 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24..4.0) # # Project details # -project("databento" VERSION 0.33.0 LANGUAGES CXX) +project( + databento + VERSION 0.34.0 + LANGUAGES CXX + DESCRIPTION "Official Databento client library" +) string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPERCASE) # @@ -83,6 +88,7 @@ endif() add_library( ${PROJECT_NAME} + STATIC ${headers} ${sources} ) @@ -101,6 +107,7 @@ message(STATUS "Added all header and implementation files.") # target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) +set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF) include(cmake/CompilerWarnings.cmake) set_target_warnings(${PROJECT_NAME}) include(cmake/Sanitizers.cmake) @@ -143,19 +150,11 @@ else() set(json_version 3.11.3) # Required to correctly install nlohmann_json set(JSON_Install ON) - if(CMAKE_VERSION VERSION_LESS 3.24) - FetchContent_Declare( - json - URL https://github.com/nlohmann/json/releases/download/v${json_version}/json.tar.xz - ) - else() - # DOWNLOAD_EXTRACT_TIMESTAMP added in 3.24 - FetchContent_Declare( - json - URL https://github.com/nlohmann/json/releases/download/v${json_version}/json.tar.xz - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - ) - endif() + FetchContent_Declare( + json + URL https://github.com/nlohmann/json/releases/download/v${json_version}/json.tar.xz + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + ) FetchContent_MakeAvailable(json) # Ignore compiler warnings in headers add_system_include_property(nlohmann_json) @@ -175,19 +174,11 @@ if(${PROJECT_NAME_UPPERCASE}_USE_EXTERNAL_HTTPLIB) endif() else() set(httplib_version 0.20.0) - if(CMAKE_VERSION VERSION_LESS 3.24) - FetchContent_Declare( - httplib - URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v${httplib_version}.tar.gz - ) - else() - # DOWNLOAD_EXTRACT_TIMESTAMP added in 3.24 - FetchContent_Declare( - httplib - URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v${httplib_version}.tar.gz - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - ) - endif() + FetchContent_Declare( + httplib + URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v${httplib_version}.tar.gz + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + ) FetchContent_MakeAvailable(httplib) # Ignore compiler warnings in headers add_system_include_property(httplib) @@ -207,19 +198,11 @@ if(${PROJECT_NAME_UPPERCASE}_USE_EXTERNAL_DATE) endif() else() set(date_version 3.0.3) - if(CMAKE_VERSION VERSION_LESS 3.24) - FetchContent_Declare( - date_src - URL https://github.com/HowardHinnant/date/archive/refs/tags/v${date_version}.tar.gz - ) - else() - # DOWNLOAD_EXTRACT_TIMESTAMP added in 3.24 - FetchContent_Declare( - date_src - URL https://github.com/HowardHinnant/date/archive/refs/tags/v${date_version}.tar.gz - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - ) - endif() + FetchContent_Declare( + date_src + URL https://github.com/HowardHinnant/date/archive/refs/tags/v${date_version}.tar.gz + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + ) FetchContent_MakeAvailable(date_src) # Ignore compiler warnings in headers add_system_include_property(date) diff --git a/README.md b/README.md index deb1cf5..dcc4199 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The client supports both streaming real-time and historical market data through ## Usage -The minimum C++ standard is C++17 and the minimum CMake version is 3.14. +The minimum C++ standard is C++17 and the minimum CMake version is 3.24. ### Integration @@ -18,7 +18,7 @@ Your `CMakeLists.txt` should look something like the following: ```cmake # CMakeLists.txt -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24) project(databento_example) include(FetchContent) diff --git a/cmake/StandardSettings.cmake b/cmake/StandardSettings.cmake index 67bdacf..3046821 100644 --- a/cmake/StandardSettings.cmake +++ b/cmake/StandardSettings.cmake @@ -75,7 +75,6 @@ if(${PROJECT_NAME_UPPERCASE}_ENABLE_CCACHE) find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND) message(STATUS "Found and enabled ccache") - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) - set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") endif() endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 951ec69..c43ccaa 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24) project( ${CMAKE_PROJECT_NAME}Examples diff --git a/examples/historical/CMakeLists.txt b/examples/historical/CMakeLists.txt index b9615f3..8665084 100644 --- a/examples/historical/CMakeLists.txt +++ b/examples/historical/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24) add_example_target(batch batch.cpp) add_example_target(metadata metadata.cpp) diff --git a/examples/live/CMakeLists.txt b/examples/live/CMakeLists.txt index cb1d9c6..fee627d 100644 --- a/examples/live/CMakeLists.txt +++ b/examples/live/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24) add_example_target(live-readme readme.cpp) add_example_target(simple simple.cpp) diff --git a/include/databento/constants.hpp b/include/databento/constants.hpp index 52eaae5..ec7e215 100644 --- a/include/databento/constants.hpp +++ b/include/databento/constants.hpp @@ -24,6 +24,8 @@ static constexpr auto kUndefTimestamp = static constexpr auto kDbnVersion = 2; // The length of fixed-length symbol strings. static constexpr auto kSymbolCstrLen = 71; +// The length of fixed-length asset string. +static constexpr auto kAssetCstrLen = 7; // The multiplier for converting the `length` field in `RecordHeader` to bytes. static constexpr std::size_t kRecordHeaderLengthMultiplier = 4; diff --git a/include/databento/enums.hpp b/include/databento/enums.hpp index d782895..8206d12 100644 --- a/include/databento/enums.hpp +++ b/include/databento/enums.hpp @@ -439,7 +439,8 @@ using trading_event::TradingEvent; // An enum for representing unknown, true, or false values. Equivalent to a // std::optional. -enum class TriState : char { +namespace tri_state { +enum TriState : char { // The value is not applicable or not known. NotAvailable = '~', // False @@ -447,6 +448,46 @@ enum class TriState : char { // True Yes = 'Y', }; +} // namespace tri_state +using tri_state::TriState; + +namespace error_code { +enum ErrorCode : std::uint8_t { + // The authentication step failed. + AuthFailed = 1, + // The user account or API key were deactivated. + ApiKeyDeactivated = 2, + // The user has exceeded their open connection limit + ConnectionLimitExceeded = 3, + // One or more symbols failed to resolve. + SymbolResolutionFailed = 4, + // There was an issue with a subscription request (other than symbol + // resolution). + InvalidSubscription = 5, + // An error occurred in the gateway. + InternalError = 6, + + Unset = 255, +}; +} // namespace error_code +using error_code::ErrorCode; + +namespace system_code { +enum SystemCode : std::uint8_t { + // A message sent in the absence of other records to indicate the connection + // remains open. + Heartbeat = 0, + // An acknowledgement of a subscription request. + SubscriptionAck = 1, + // The gateway has detected this session is falling behind real-time. + SlowReaderWarning = 2, + // Indicates a replay subscription has caught up with real-time data. + ReplayCompleted = 3, + + Unset = 255, +}; +} // namespace system_code +using system_code::SystemCode; // Convert a HistoricalGateway to a URL. const char* UrlFromGateway(HistoricalGateway gateway); @@ -474,6 +515,8 @@ const char* ToString(StatusReason status_reason); const char* ToString(TradingEvent trading_event); const char* ToString(TriState tri_state); const char* ToString(VersionUpgradePolicy upgrade_policy); +const char* ToString(ErrorCode error_code); +const char* ToString(SystemCode system_code); std::ostream& operator<<(std::ostream& out, Schema schema); std::ostream& operator<<(std::ostream& out, Encoding encoding); @@ -501,6 +544,8 @@ std::ostream& operator<<(std::ostream& out, TradingEvent trading_event); std::ostream& operator<<(std::ostream& out, TriState tri_state); std::ostream& operator<<(std::ostream& out, VersionUpgradePolicy upgrade_policy); +std::ostream& operator<<(std::ostream& out, ErrorCode error_code); +std::ostream& operator<<(std::ostream& out, SystemCode system_code); template <> Schema FromString(const std::string& str); diff --git a/include/databento/record.hpp b/include/databento/record.hpp index a526e75..c238ee3 100644 --- a/include/databento/record.hpp +++ b/include/databento/record.hpp @@ -4,6 +4,7 @@ #include #include #include // strncmp +#include #include #include // tie #include @@ -433,7 +434,7 @@ struct InstrumentDefMsg { std::array raw_symbol; std::array group; std::array exchange; - std::array asset; + std::array asset; std::array cfi; std::array security_type; std::array unit_of_measure; @@ -528,7 +529,7 @@ struct ErrorMsg { RecordHeader hd; std::array err; - std::uint8_t code; + ErrorCode code; std::uint8_t is_last; }; static_assert(sizeof(ErrorMsg) == 320, "ErrorMsg size must match Rust"); @@ -560,12 +561,17 @@ struct SystemMsg { UnixNanos IndexTs() const { return hd.ts_event; } const char* Msg() const { return msg.data(); } bool IsHeartbeat() const { - return std::strncmp(msg.data(), "Heartbeat", 9) == 0; + // Check if code is unset + if (static_cast(code) == + std::numeric_limits::max()) { + return std::strncmp(msg.data(), "Heartbeat", 9) == 0; + } + return code == SystemCode::Heartbeat; } RecordHeader hd; std::array msg; - std::uint8_t code; + SystemCode code; }; static_assert(sizeof(SystemMsg) == 320, "SystemMsg size must match Rust"); static_assert(alignof(SystemMsg) == 8, "Must have 8-byte alignment"); diff --git a/include/databento/v1.hpp b/include/databento/v1.hpp index e076f3b..cb206ae 100644 --- a/include/databento/v1.hpp +++ b/include/databento/v1.hpp @@ -1,6 +1,7 @@ #pragma once -#include "databento/datetime.hpp" // UnixNanos +#include "databento/constants.hpp" // kSymbolCstrLen +#include "databento/datetime.hpp" // UnixNanos #include "databento/enums.hpp" #include "databento/record.hpp" #include "databento/v2.hpp" @@ -13,6 +14,7 @@ struct InstrumentDefMsg; namespace v1 { static constexpr std::size_t kSymbolCstrLen = 22; +static constexpr std::size_t kAssetCstrLen = databento::kAssetCstrLen; using MboMsg = databento::MboMsg; using TradeMsg = databento::TradeMsg; @@ -92,7 +94,7 @@ struct InstrumentDefMsg { std::array raw_symbol; std::array group; std::array exchange; - std::array asset; + std::array asset; std::array cfi; std::array security_type; std::array unit_of_measure; diff --git a/include/databento/v2.hpp b/include/databento/v2.hpp index a21b106..e64ccd4 100644 --- a/include/databento/v2.hpp +++ b/include/databento/v2.hpp @@ -5,6 +5,7 @@ namespace databento::v2 { static constexpr std::size_t kSymbolCstrLen = databento::kSymbolCstrLen; +static constexpr std::size_t kAssetCstrLen = databento::kAssetCstrLen; using MboMsg = databento::MboMsg; using TradeMsg = databento::TradeMsg; diff --git a/include/databento/v3.hpp b/include/databento/v3.hpp index 71c0c2f..5472712 100644 --- a/include/databento/v3.hpp +++ b/include/databento/v3.hpp @@ -10,6 +10,7 @@ namespace databento::v3 { static constexpr std::size_t kSymbolCstrLen = databento::kSymbolCstrLen; +static constexpr std::size_t kAssetCstrLen = 11; using MboMsg = databento::MboMsg; using TradeMsg = databento::TradeMsg; @@ -100,7 +101,7 @@ struct InstrumentDefMsg { std::array raw_symbol; std::array group; std::array exchange; - std::array asset; + std::array asset; std::array cfi; std::array security_type; std::array unit_of_measure; @@ -124,7 +125,7 @@ struct InstrumentDefMsg { InstrumentClass leg_instrument_class; Side leg_side; // padding for alignment - std::array reserved; + std::array reserved; }; static_assert(sizeof(InstrumentDefMsg) == 520, "InstrumentDefMsg size must match Rust"); diff --git a/pkg/PKGBUILD b/pkg/PKGBUILD index 35b290a..d3ab559 100644 --- a/pkg/PKGBUILD +++ b/pkg/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Databento _pkgname=databento-cpp pkgname=databento-cpp-git -pkgver=0.33.0 +pkgver=0.34.0 pkgrel=1 pkgdesc="Official C++ client for Databento" arch=('any') diff --git a/src/enums.cpp b/src/enums.cpp index 3eb20f8..1ac00aa 100644 --- a/src/enums.cpp +++ b/src/enums.cpp @@ -760,6 +760,52 @@ const char* ToString(VersionUpgradePolicy upgrade_policy) { } } +const char* ToString(ErrorCode error_code) { + switch (error_code) { + case ErrorCode::AuthFailed: { + return "auth_failed"; + } + case ErrorCode::ApiKeyDeactivated: { + return "api_key_deactivated"; + } + case ErrorCode::ConnectionLimitExceeded: { + return "connection_limit_exceeded"; + } + case ErrorCode::SymbolResolutionFailed: { + return "symbol_resolution_failed"; + } + case ErrorCode::InvalidSubscription: { + return "invalid_subscription"; + } + case ErrorCode::InternalError: { + return "internal_error"; + } + default: { + return "Unknown"; + } + } +} + +const char* ToString(SystemCode system_code) { + switch (system_code) { + case SystemCode::Heartbeat: { + return "heartbeat"; + } + case SystemCode::SubscriptionAck: { + return "subscription_ack"; + } + case SystemCode::SlowReaderWarning: { + return "slow_reader_warning"; + } + case SystemCode::ReplayCompleted: { + return "replay_completed"; + } + default: { + return "Unknown"; + } + } +} + std::ostream& operator<<(std::ostream& out, Schema schema) { out << ToString(schema); return out; @@ -876,6 +922,16 @@ std::ostream& operator<<(std::ostream& out, return out; } +std::ostream& operator<<(std::ostream& out, ErrorCode error_code) { + out << ToString(error_code); + return out; +} + +std::ostream& operator<<(std::ostream& out, SystemCode system_code) { + out << ToString(system_code); + return out; +} + template <> Schema FromString(const std::string& str) { if (str == "mbo") { diff --git a/src/v1.cpp b/src/v1.cpp index 59d2548..2d7a137 100644 --- a/src/v1.cpp +++ b/src/v1.cpp @@ -2,9 +2,11 @@ #include // copy #include +#include #include // numeric_limits #include "databento/constants.hpp" +#include "databento/enums.hpp" #include "databento/fixed_price.hpp" // FixedPx #include "databento/record.hpp" #include "databento/v2.hpp" @@ -193,7 +195,7 @@ v2::ErrorMsg ErrorMsg::ToV2() const { RType::Error, hd.publisher_id, hd.instrument_id, hd.ts_event}, {}, - std::numeric_limits::max(), + ErrorCode::Unset, std::numeric_limits::max()}; std::copy(err.begin(), err.end(), ret.err.begin()); return ret; @@ -227,7 +229,7 @@ v2::SystemMsg SystemMsg::ToV2() const { RType::System, hd.publisher_id, hd.instrument_id, hd.ts_event}, {}, - std::numeric_limits::max()}; + IsHeartbeat() ? SystemCode::Heartbeat : SystemCode::Unset}; std::copy(msg.begin(), msg.end(), ret.msg.begin()); return ret; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f7ed013..d1868fa 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24) # # Project details diff --git a/tests/cmake_fetch_content/project/CMakeLists.txt b/tests/cmake_fetch_content/project/CMakeLists.txt index c902184..1f04039 100644 --- a/tests/cmake_fetch_content/project/CMakeLists.txt +++ b/tests/cmake_fetch_content/project/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24) project(DummyImport LANGUAGES CXX) diff --git a/tests/cmake_import/project/CMakeLists.txt b/tests/cmake_import/project/CMakeLists.txt index 193e6fe..1632e07 100644 --- a/tests/cmake_import/project/CMakeLists.txt +++ b/tests/cmake_import/project/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.24) project(DummyImport LANGUAGES CXX)