Skip to content

Commit

Permalink
messages: throw AccessException when trying to access invalid field/i…
Browse files Browse the repository at this point in the history
…ndex

And check for it in the ulog_data example
  • Loading branch information
bkueng committed Feb 1, 2024
1 parent 94f6ae0 commit f3981ec
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 30 deletions.
51 changes: 30 additions & 21 deletions examples/ulog_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ int main(int argc, char** argv)
for (const auto& sub : subscription_names) {
std::cout << sub << "\n";
}
std::cout << "\n";

// Get a particular subscription
if (subscription_names.find("vehicle_status") != subscription_names.end()) {
Expand All @@ -62,30 +63,34 @@ int main(int argc, char** argv)
std::cout << "Field names: "
<< "\n";
for (const std::string& field : subscription->fieldNames()) {
std::cout << field << "\n";
std::cout << " " << field << "\n";
}

// Get particular field
auto nav_state_field = subscription->field("nav_state");
try {
auto nav_state_field = subscription->field("nav_state");

// Iterate over all samples
std::cout << "nav_state values: \n";
for (const auto& sample : *subscription) {
// always correctly extracts the type as defined in the message definition,
// gets cast to the value you put in int.
// This also works for arrays and strings.
auto nav_state = sample[nav_state_field].as<int>();
std::cout << nav_state << ", ";
}
std::cout << "\n";
// Iterate over all samples
std::cout << "nav_state values: \n ";
for (const auto& sample : *subscription) {
// always correctly extracts the type as defined in the message definition,
// gets cast to the value you put in int.
// This also works for arrays and strings.
auto nav_state = sample[nav_state_field].as<int>();
std::cout << nav_state << ", ";
}
std::cout << "\n";

// get a specific sample
auto sample_12 = subscription->at(12);
// get a specific sample
auto sample_12 = subscription->at(12);

// access values by name
auto timestamp = sample_12["timestamp"].as<uint64_t>();
// access values by name
auto timestamp = sample_12["timestamp"].as<uint64_t>();

std::cout << timestamp << "\n";
std::cout << "timestamp at sample 12: " << timestamp << "\n";
} catch (const ulog_cpp::AccessException& exception) {
std::cout << "AccessException: " << exception.what() << "\n";
}
} else {
std::cout << "No vehicle_status subscription found\n";
}
Expand All @@ -95,16 +100,20 @@ int main(int argc, char** argv)
const auto& message_format = data_container->messageFormats().at("esc_status");
std::cout << "Message format: " << message_format->name() << "\n";
for (const auto& field_name : message_format->fieldNames()) {
std::cout << field_name << "\n";
std::cout << " " << field_name << "\n";
}
} else {
std::cout << "No esc_status message format found\n";
}

if (subscription_names.find("esc_status") != subscription_names.end()) {
auto esc_status = data_container->subscription("esc_status");
for (const auto& sample : *esc_status) {
std::cout << "esc_power: " << sample["esc"][7]["esc_power"].as<int>() << "\n";
try {
auto esc_status = data_container->subscription("esc_status");
for (const auto& sample : *esc_status) {
std::cout << "esc_power: " << sample["esc"][7]["esc_power"].as<int>() << "\n";
}
} catch (const ulog_cpp::AccessException& exception) {
std::cout << "AccessException: " << exception.what() << "\n";
}
} else {
std::cout << "No esc_status subscription found\n";
Expand Down
6 changes: 6 additions & 0 deletions test/read_api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ TEST_CASE("Write complicated, nested data format, then read it")
sample[f_child_1][f_c1_c1_2][2][f_c1_c1_2_byte_b].asNativeTypeVariant()));
CHECK(std::holds_alternative<std::vector<uint64_t>>(
sample[f_child_1][f_c1_unsigned_long].asNativeTypeVariant()));

// Check exceptions
CHECK_THROWS_AS(sample["non_existent"], ulog_cpp::AccessException);
CHECK_THROWS_AS(sample[f_child_1][f_c1_unsigned_long][100], ulog_cpp::AccessException);
CHECK_THROWS_AS(data_container->subscription("non_existent_subscription"),
ulog_cpp::AccessException);
}

TEST_SUITE_END();
13 changes: 6 additions & 7 deletions ulog_cpp/data_container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,13 @@ class DataContainer : public DataHandlerInterface {
return names;
}

std::shared_ptr<Subscription> subscription(const std::string& name, int multi_id) const
std::shared_ptr<Subscription> subscription(const std::string& name, int multi_id = 0) const
{
return _subscriptions_by_name_and_multi_id.at({name, multi_id});
}

std::shared_ptr<Subscription> subscription(const std::string& name) const
{
return _subscriptions_by_name_and_multi_id.at({name, 0});
const auto it = _subscriptions_by_name_and_multi_id.find({name, multi_id});
if (it == _subscriptions_by_name_and_multi_id.end()) {
throw AccessException("Subscription not found: " + name);
}
return it->second;
}

protected:
Expand Down
9 changes: 8 additions & 1 deletion ulog_cpp/messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,14 @@ class MessageFormat {
* @param name the name of the field
* @return the requested field
*/
std::shared_ptr<Field> field(const std::string& name) const { return _fields.at(name); }
std::shared_ptr<Field> field(const std::string& name) const
{
const auto it = _fields.find(name);
if (it == _fields.end()) {
throw AccessException("Field not found: " + name);
}
return it->second;
}

private:
std::string _name;
Expand Down
8 changes: 7 additions & 1 deletion ulog_cpp/subscription.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,13 @@ class Subscription {
_message_format);
}

TypedDataView at(std::size_t n) const { return begin()[n]; }
TypedDataView at(std::size_t n) const
{
if (n >= size()) {
throw AccessException("Index out of range: " + std::to_string(n));
}
return begin()[n];
}

TypedDataView operator[](std::size_t n) { return at(n); }

Expand Down

0 comments on commit f3981ec

Please sign in to comment.