Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.44.0 - 2025-11-18

### Enhancements
- Added logic to set `code` when upgrading version 1 `SystemMsg` to newer versions

### Bug fixes
- Added missing `<cstddef>` include to `constants.hpp` (credit: @ognian-)

## 0.43.0 - 2025-10-21

### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24..4.0)

project(
databento
VERSION 0.43.0
VERSION 0.44.0
LANGUAGES CXX
DESCRIPTION "Official Databento client library"
)
Expand Down
1 change: 1 addition & 0 deletions include/databento/constants.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <cstddef>
#include <cstdint>
#include <limits>

Expand Down
5 changes: 3 additions & 2 deletions include/databento/enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ namespace trading_event {
enum TradingEvent : std::uint16_t {
// No additional information given.
None = 0,
// Order entry and modification are not allowed.
// Order entry is allowed. Modification and cancellation are not allowed.
NoCancel = 1,
// A change of trading session occurred. Daily statistics are reset.
ChangeTradingSession = 2,
Expand Down Expand Up @@ -633,7 +633,8 @@ enum SystemCode : std::uint8_t {
// given timestamp.
EndOfInterval = 4,
// No system code was specified or this record was upgraded from a version 1 struct
// where the code field didn't exist.
// where
// the code field didn't exist.
Unset = 255,
};
} // namespace system_code
Expand Down
2 changes: 1 addition & 1 deletion pkg/PKGBUILD
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Maintainer: Databento <support@databento.com>
_pkgname=databento-cpp
pkgname=databento-cpp-git
pkgver=0.43.0
pkgver=0.44.0
pkgrel=1
pkgdesc="Official C++ client for Databento"
arch=('any')
Expand Down
33 changes: 31 additions & 2 deletions src/v1.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "databento/v1.hpp"

#include <algorithm> // copy
#include <cstddef> // size_t
#include <cstdint>
#include <limits> // numeric_limits
#include <cstring> // strlen, strncmp
#include <limits> // numeric_limits

#include "databento/enums.hpp"
#include "databento/pretty.hpp" // Px
Expand Down Expand Up @@ -239,8 +241,35 @@ v2::SystemMsg SystemMsg::ToV2() const {
RecordHeader{sizeof(v2::SystemMsg) / RecordHeader::kLengthMultiplier,
RType::System, hd.publisher_id, hd.instrument_id, hd.ts_event},
{},
IsHeartbeat() ? SystemCode::Heartbeat : SystemCode::Unset};
SystemCode::Unset};
std::copy(msg.begin(), msg.end(), ret.msg.begin());
// No standardized strnlen
const auto null_it = std::find(msg.begin(), msg.end(), '\0');
if (null_it != msg.end()) {
constexpr auto kEndOfInterval = "End of interval for ";
constexpr auto kSubAckStart = "Subscription request ";
constexpr auto kSubAckEnd = " succeeded";
constexpr auto kSlowReader = "Warning: slow reading";
constexpr auto kFinishedStart = "Finished ";
constexpr auto kFinishedEnd = " replay";

const auto msg_len = static_cast<std::size_t>(null_it - msg.begin());
if (IsHeartbeat()) {
ret.code = SystemCode::Heartbeat;
} else if (std::strncmp(Msg(), kEndOfInterval, std::strlen(kEndOfInterval)) == 0) {
ret.code = SystemCode::EndOfInterval;
} else if (std::strncmp(Msg(), kSubAckStart, std::strlen(kSubAckStart)) == 0 &&
std::strncmp(&Msg()[msg_len - std::strlen(kSubAckEnd)], kSubAckEnd,
std::strlen(kSubAckEnd)) == 0) {
ret.code = SystemCode::SubscriptionAck;
} else if (std::strncmp(Msg(), kSlowReader, std::strlen(kSlowReader)) == 0) {
ret.code = SystemCode::SlowReaderWarning;
} else if (std::strncmp(Msg(), kFinishedStart, std::strlen(kFinishedStart)) == 0 &&
std::strncmp(&Msg()[msg_len - std::strlen(kFinishedEnd)], kFinishedEnd,
std::strlen(kFinishedEnd)) == 0) {
ret.code = SystemCode::ReplayCompleted;
}
}
return ret;
}

Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ set(
src/symbol_map_tests.cpp
src/symbology_tests.cpp
src/tcp_client_tests.cpp
src/v1_tests.cpp
src/zstd_stream_tests.cpp
)
add_executable(${PROJECT_NAME} ${test_headers} ${test_sources})
Expand Down
42 changes: 42 additions & 0 deletions tests/src/v1_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <gtest/gtest.h>

#include <cstring> // strcpy

#include "databento/enums.hpp"
#include "databento/record.hpp"
#include "databento/v1.hpp"

namespace databento::v1::tests {
TEST(V1Tests, TestSystemMsgCodeUpgrade) {
v1::SystemMsg target{
RecordHeader{sizeof(v1::SystemMsg) / RecordHeader::kLengthMultiplier,
RType::System,
0,
0,
{}}};
std::strcpy(target.msg.data(), "Heartbeat");
const auto res1 = target.ToV2();
EXPECT_EQ(res1.code, SystemCode::Heartbeat);

target.msg = {};
std::strcpy(target.msg.data(), "End of interval for bbo-1s");
const auto res2 = target.ToV2();
EXPECT_EQ(res2.code, SystemCode::EndOfInterval);

target.msg = {};
std::strcpy(target.msg.data(), "Subscription request 5 for mbo data succeeded");
const auto res3 = target.ToV2();
EXPECT_EQ(res3.code, SystemCode::SubscriptionAck);

target.msg = {};
std::strcpy(target.msg.data(),
"Warning: slow reading, not keeping pace with cbbo-1s data");
const auto res4 = target.ToV2();
EXPECT_EQ(res4.code, SystemCode::SlowReaderWarning);

target.msg = {};
std::strcpy(target.msg.data(), "Finished ohlcv-1s replay");
const auto res5 = target.ToV2();
EXPECT_EQ(res5.code, SystemCode::ReplayCompleted);
}
} // namespace databento::v1::tests
Loading