Skip to content

Commit 246e14d

Browse files
committed
VER: Release 0.18.1
1 parent 4d3ce49 commit 246e14d

File tree

10 files changed

+78
-20
lines changed

10 files changed

+78
-20
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
# Changelog
22

3-
## 0.18.1 - TBD
3+
## 0.18.1 - 2024-05-22
44

55
### Enhancements
66
- Added live `Subscribe` function overload with `use_snapshot` parameter
7+
- Added `GetIf` method to `Record` that allows `if` chaining for handling multiple
8+
record types
9+
- Added record type checking to `Record::Get` method to catch programming errors
10+
and prevent reading invalid data
711

812
### Bug fixes
913
- Added missing symbol chunking for live `Subscribe` overloads with `const std::string&`

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.14)
44
# Project details
55
#
66

7-
project("databento" VERSION 0.18.0 LANGUAGES CXX)
7+
project("databento" VERSION 0.18.1 LANGUAGES CXX)
88
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPERCASE)
99

1010
#

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,9 @@ int main() {
108108

109109
auto handler = [&symbol_mappings](const Record& rec) {
110110
symbol_mappings.OnRecord(rec);
111-
if (rec.Holds<TradeMsg>()) {
112-
auto trade = rec.Get<TradeMsg>();
111+
if (const auto* trade = rec.GetIf<TradeMsg>()) {
113112
std::cout << "Received trade for "
114-
<< symbol_mappings[trade.hd.instrument_id] << ':' << trade
113+
<< symbol_mappings[trade->hd.instrument_id] << ':' << *trade
115114
<< '\n';
116115
}
117116
return KeepGoing::Continue;

example/live/readme.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ int main() {
1818

1919
auto handler = [&symbol_mappings](const Record& rec) {
2020
symbol_mappings.OnRecord(rec);
21-
if (rec.Holds<TradeMsg>()) {
22-
auto trade = rec.Get<TradeMsg>();
21+
if (const auto* trade = rec.GetIf<TradeMsg>()) {
2322
std::cout << "Received trade for "
24-
<< symbol_mappings[trade.hd.instrument_id] << ':' << trade
23+
<< symbol_mappings[trade->hd.instrument_id] << ':' << *trade
2524
<< '\n';
2625
}
2726
return KeepGoing::Continue;

include/databento/record.hpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "databento/constants.hpp" // kSymbolCstrLen
1111
#include "databento/datetime.hpp" // UnixNanos
1212
#include "databento/enums.hpp"
13+
#include "databento/exceptions.hpp" // InvalidArgumentError
1314
#include "databento/flag_set.hpp" // FlagSet
1415
#include "databento/publishers.hpp" // Publisher
1516
#include "databento/with_ts_out.hpp"
@@ -54,11 +55,33 @@ class Record {
5455

5556
template <typename T>
5657
const T& Get() const {
57-
return *reinterpret_cast<const T*>(record_);
58+
if (const auto* r = GetIf<T>()) {
59+
return *r;
60+
}
61+
throw InvalidArgumentError{
62+
"Get", "T", std::string{"rtype mismatch, found "} + ToString(RType())};
5863
}
5964
template <typename T>
6065
T& Get() {
61-
return *reinterpret_cast<T*>(record_);
66+
if (auto* r = GetIf<T>()) {
67+
return *r;
68+
}
69+
throw InvalidArgumentError{
70+
"Get", "T", std::string{"rtype mismatch, found "} + ToString(RType())};
71+
}
72+
template <typename T>
73+
const T* GetIf() const {
74+
if (!Holds<T>()) {
75+
return nullptr;
76+
}
77+
return reinterpret_cast<const T*>(record_);
78+
}
79+
template <typename T>
80+
T* GetIf() {
81+
if (!Holds<T>()) {
82+
return nullptr;
83+
}
84+
return reinterpret_cast<T*>(record_);
6285
}
6386

6487
std::size_t Size() const;
@@ -629,6 +652,8 @@ inline bool operator!=(const SymbolMappingMsg& lhs,
629652

630653
std::string ToString(const RecordHeader& header);
631654
std::ostream& operator<<(std::ostream& stream, const RecordHeader& header);
655+
std::string ToString(const Record& header);
656+
std::ostream& operator<<(std::ostream& stream, const Record& header);
632657
std::string ToString(const MboMsg& mbo_msg);
633658
std::ostream& operator<<(std::ostream& stream, const MboMsg& mbo_msg);
634659
std::string ToString(const BidAskPair& ba_pair);

pkg/PKGBUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Maintainer: Databento <support@databento.com>
22
_pkgname=databento-cpp
33
pkgname=databento-cpp-git
4-
pkgver=0.18.0
4+
pkgver=0.18.1
55
pkgrel=1
66
pkgdesc="Official C++ client for Databento"
77
arch=('any')

src/record.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,15 @@ bool databento::operator==(const ImbalanceMsg& lhs, const ImbalanceMsg& rhs) {
189189
}
190190

191191
namespace databento {
192-
192+
std::string ToString(const Record& record) { return MakeString(record); }
193+
std::ostream& operator<<(std::ostream& stream, const Record& record) {
194+
return StreamOpBuilder{stream}
195+
.SetSpacer(" ")
196+
.SetTypeName("Record")
197+
.Build()
198+
.AddField("ptr", record.Header())
199+
.Finish();
200+
}
193201
std::string ToString(const RecordHeader& header) { return MakeString(header); }
194202
std::ostream& operator<<(std::ostream& stream, const RecordHeader& header) {
195203
return StreamOpBuilder{stream}

test/src/live_blocking_tests.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,19 +169,20 @@ TEST_F(LiveBlockingTests, TestSubscribeSnapshot) {
169169
const std::size_t kSymbolCount = 1000;
170170
const auto kSchema = Schema::Ohlcv1M;
171171
const auto kSType = SType::RawSymbol;
172-
const auto use_snapshot = true;
172+
const auto kUseSnapshot = true;
173173

174174
const mock::MockLsgServer mock_server{
175175
kDataset, kTsOut,
176-
[kSymbol, kSymbolCount, kSchema, kSType](mock::MockLsgServer& self) {
176+
[kSymbol, kSymbolCount, kSchema, kSType,
177+
kUseSnapshot](mock::MockLsgServer& self) {
177178
self.Accept();
178179
self.Authenticate();
179180
std::size_t i{};
180181
while (i < 1000) {
181182
const auto chunk_size =
182183
std::min(static_cast<std::size_t>(128), kSymbolCount - i);
183184
const std::vector<std::string> symbols_chunk(chunk_size, kSymbol);
184-
self.Subscribe(symbols_chunk, kSchema, kSType, use_snapshot);
185+
self.Subscribe(symbols_chunk, kSchema, kSType, kUseSnapshot);
185186
i += chunk_size;
186187
}
187188
}};
@@ -194,7 +195,7 @@ TEST_F(LiveBlockingTests, TestSubscribeSnapshot) {
194195
kTsOut,
195196
VersionUpgradePolicy{}};
196197
const std::vector<std::string> kSymbols(kSymbolCount, kSymbol);
197-
target.Subscribe(kSymbols, kSchema, kSType, use_snapshot);
198+
target.Subscribe(kSymbols, kSchema, kSType, kUseSnapshot);
198199
}
199200

200201
TEST_F(LiveBlockingTests, TestInvalidSubscription) {

test/src/live_threaded_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,17 +178,17 @@ TEST_F(LiveThreadedTests, TestExceptionCallbackAndReconnect) {
178178
{},
179179
2};
180180

181-
const auto use_snapshot = true;
181+
const auto kUseSnapshot = true;
182182
bool should_close{};
183183
std::mutex should_close_mutex;
184184
std::condition_variable should_close_cv;
185185
const mock::MockLsgServer mock_server{
186186
dataset::kXnasItch, kTsOut,
187187
[&should_close, &should_close_mutex, &should_close_cv, kRec, kSchema,
188-
kSType](mock::MockLsgServer& self) {
188+
kSType, kUseSnapshot](mock::MockLsgServer& self) {
189189
self.Accept();
190190
self.Authenticate();
191-
self.Subscribe(kAllSymbols, kSchema, kSType, use_snapshot);
191+
self.Subscribe(kAllSymbols, kSchema, kSType, kUseSnapshot);
192192
self.Start();
193193
{
194194
std::unique_lock<std::mutex> shutdown_lock{should_close_mutex};
@@ -237,7 +237,7 @@ TEST_F(LiveThreadedTests, TestExceptionCallbackAndReconnect) {
237237
}
238238
};
239239

240-
target.Subscribe(kAllSymbols, kSchema, kSType, use_snapshot);
240+
target.Subscribe(kAllSymbols, kSchema, kSType, kUseSnapshot);
241241
target.Start(metadata_cb, record_cb, exception_cb);
242242
target.BlockForStop();
243243
EXPECT_EQ(metadata_calls, 2);

test/src/record_tests.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,28 @@
1111

1212
namespace databento {
1313
namespace test {
14+
TEST(RecordTests, TestRecordToString) {
15+
TradeMsg target{
16+
RecordHeader{sizeof(TradeMsg) / RecordHeader::kLengthMultiplier,
17+
RType::Mbp0,
18+
static_cast<std::uint16_t>(Publisher::OpraPillarEdgo),
19+
1,
20+
{}},
21+
55000000000,
22+
500,
23+
Action::Add,
24+
Side::Bid,
25+
{},
26+
0,
27+
{},
28+
{},
29+
126239};
30+
const Record rec{&target.hd};
31+
EXPECT_EQ(
32+
ToString(rec),
33+
"Record { ptr = RecordHeader { length = 12, rtype = Mbp0, publisher_id = "
34+
"24, instrument_id = 1, ts_event = 1970-01-01T00:00:00.000000000Z } }");
35+
}
1436
TEST(RecordTests, TestPublisher) {
1537
const TradeMsg target{
1638
RecordHeader{sizeof(TradeMsg) / RecordHeader::kLengthMultiplier,

0 commit comments

Comments
 (0)