mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[ntcore] Refactor meta-topic decoding from glass (#4809)
This commit is contained in:
@@ -600,138 +600,42 @@ NetworkTablesModel::Entry* NetworkTablesModel::AddEntry(NT_Topic topic) {
|
||||
return entry.get();
|
||||
}
|
||||
|
||||
NetworkTablesModel::Client::Subscriber::Subscriber(
|
||||
nt::meta::ClientSubscriber&& oth)
|
||||
: ClientSubscriber{std::move(oth)},
|
||||
topicsStr{StringArrayToString(topics)} {}
|
||||
|
||||
void NetworkTablesModel::Client::UpdatePublishers(
|
||||
std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numPub = mpack_expect_array_max(&r, 1000);
|
||||
std::vector<ClientPublisher> newPublishers;
|
||||
newPublishers.reserve(numPub);
|
||||
for (uint32_t i = 0; i < numPub; ++i) {
|
||||
ClientPublisher pub;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "uid") {
|
||||
pub.uid = mpack_expect_i64(&r);
|
||||
} else if (key == "topic") {
|
||||
mpack_expect_str(&r, &pub.topic);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
newPublishers.emplace_back(std::move(pub));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) == mpack_ok) {
|
||||
publishers = std::move(newPublishers);
|
||||
if (auto pubs = nt::meta::DecodeClientPublishers(data)) {
|
||||
publishers = std::move(*pubs);
|
||||
} else {
|
||||
fmt::print(stderr, "Failed to update publishers\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void DecodeSubscriberOptions(
|
||||
mpack_reader_t& r, NetworkTablesModel::SubscriberOptions* options) {
|
||||
*options = NetworkTablesModel::SubscriberOptions{};
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "topicsonly") {
|
||||
options->topicsOnly = mpack_expect_bool(&r);
|
||||
} else if (key == "all") {
|
||||
options->sendAll = mpack_expect_bool(&r);
|
||||
} else if (key == "periodic") {
|
||||
options->periodic = mpack_expect_float(&r);
|
||||
} else if (key == "prefix") {
|
||||
options->prefixMatch = mpack_expect_bool(&r);
|
||||
} else {
|
||||
// TODO: Save other options
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
}
|
||||
|
||||
void NetworkTablesModel::Client::UpdateSubscribers(
|
||||
std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numSub = mpack_expect_array_max(&r, 1000);
|
||||
std::vector<ClientSubscriber> newSubscribers;
|
||||
newSubscribers.reserve(numSub);
|
||||
for (uint32_t i = 0; i < numSub; ++i) {
|
||||
ClientSubscriber sub;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "uid") {
|
||||
sub.uid = mpack_expect_i64(&r);
|
||||
} else if (key == "topics") {
|
||||
uint32_t numPrefix = mpack_expect_array_max(&r, 100);
|
||||
sub.topics.reserve(numPrefix);
|
||||
for (uint32_t k = 0; k < numPrefix; ++k) {
|
||||
std::string val;
|
||||
if (mpack_expect_str(&r, &val) == mpack_ok) {
|
||||
sub.topics.emplace_back(std::move(val));
|
||||
}
|
||||
}
|
||||
sub.topicsStr = StringArrayToString(sub.topics);
|
||||
mpack_done_array(&r);
|
||||
} else if (key == "options") {
|
||||
DecodeSubscriberOptions(r, &sub.options);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
if (auto subs = nt::meta::DecodeClientSubscribers(data)) {
|
||||
subscribers.clear();
|
||||
subscribers.reserve(subs->size());
|
||||
for (auto&& sub : *subs) {
|
||||
subscribers.emplace_back(std::move(sub));
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
newSubscribers.emplace_back(std::move(sub));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) == mpack_ok) {
|
||||
subscribers = std::move(newSubscribers);
|
||||
} else {
|
||||
fmt::print(stderr, "Failed to update subscribers\n");
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkTablesModel::UpdateClients(std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numClients = mpack_expect_array_max(&r, 100);
|
||||
std::vector<Client> clientsArr;
|
||||
clientsArr.reserve(numClients);
|
||||
for (uint32_t i = 0; i < numClients; ++i) {
|
||||
Client client;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "id") {
|
||||
mpack_expect_str(&r, &client.id);
|
||||
} else if (key == "conn") {
|
||||
mpack_expect_str(&r, &client.conn);
|
||||
} else if (key == "ver") {
|
||||
uint16_t val = mpack_expect_u16(&r);
|
||||
client.version = fmt::format("{}.{}", val >> 8, val & 0xff);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
clientsArr.emplace_back(std::move(client));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) != mpack_ok) {
|
||||
auto clientsArr = nt::meta::DecodeClients(data);
|
||||
if (!clientsArr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we need to create a new map so deletions are reflected
|
||||
std::map<std::string, Client, std::less<>> newClients;
|
||||
for (auto&& client : clientsArr) {
|
||||
for (auto&& client : *clientsArr) {
|
||||
auto& newClient = newClients[client.id];
|
||||
newClient = std::move(client);
|
||||
auto it = m_clients.find(newClient.id);
|
||||
@@ -1499,8 +1403,8 @@ void glass::DisplayNetworkTablesInfo(NetworkTablesModel* model) {
|
||||
if (CollapsingHeader(client.second.id.c_str())) {
|
||||
PushID(client.second.id.c_str());
|
||||
ImGui::Indent();
|
||||
ImGui::Text("%s (version %s)", client.second.conn.c_str(),
|
||||
client.second.version.c_str());
|
||||
ImGui::Text("%s (version %u.%u)", client.second.conn.c_str(),
|
||||
client.second.version >> 8, client.second.version & 0xff);
|
||||
DisplayClient(client.second);
|
||||
ImGui::Unindent();
|
||||
PopID();
|
||||
|
||||
@@ -28,25 +28,6 @@ class DataSource;
|
||||
|
||||
class NetworkTablesModel : public Model {
|
||||
public:
|
||||
struct SubscriberOptions {
|
||||
float periodic = 0.1f;
|
||||
bool topicsOnly = false;
|
||||
bool sendAll = false;
|
||||
bool prefixMatch = false;
|
||||
// std::string otherStr;
|
||||
};
|
||||
|
||||
struct TopicPublisher {
|
||||
std::string client;
|
||||
uint64_t pubuid;
|
||||
};
|
||||
|
||||
struct TopicSubscriber {
|
||||
std::string client;
|
||||
uint64_t subuid;
|
||||
SubscriberOptions options;
|
||||
};
|
||||
|
||||
struct EntryValueTreeNode;
|
||||
|
||||
struct ValueSource {
|
||||
@@ -103,8 +84,8 @@ class NetworkTablesModel : public Model {
|
||||
/** Publisher (created when the value changes). */
|
||||
NT_Publisher publisher{0};
|
||||
|
||||
std::vector<TopicPublisher> publishers;
|
||||
std::vector<TopicSubscriber> subscribers;
|
||||
std::vector<nt::meta::TopicPublisher> publishers;
|
||||
std::vector<nt::meta::TopicSubscriber> subscribers;
|
||||
};
|
||||
|
||||
struct TreeNode {
|
||||
@@ -126,24 +107,18 @@ class NetworkTablesModel : public Model {
|
||||
std::vector<TreeNode> children;
|
||||
};
|
||||
|
||||
struct ClientPublisher {
|
||||
int64_t uid = -1;
|
||||
std::string topic;
|
||||
};
|
||||
struct Client : public nt::meta::Client {
|
||||
Client() = default;
|
||||
/*implicit*/ Client(nt::meta::Client&& oth) // NOLINT
|
||||
: nt::meta::Client{std::move(oth)} {}
|
||||
|
||||
struct ClientSubscriber {
|
||||
int64_t uid = -1;
|
||||
std::vector<std::string> topics;
|
||||
std::string topicsStr;
|
||||
SubscriberOptions options;
|
||||
};
|
||||
struct Subscriber : public nt::meta::ClientSubscriber {
|
||||
/*implicit*/ Subscriber(nt::meta::ClientSubscriber&& oth); // NOLINT
|
||||
std::string topicsStr;
|
||||
};
|
||||
|
||||
struct Client {
|
||||
std::string id;
|
||||
std::string conn;
|
||||
std::string version;
|
||||
std::vector<ClientPublisher> publishers;
|
||||
std::vector<ClientSubscriber> subscribers;
|
||||
std::vector<nt::meta::ClientPublisher> publishers;
|
||||
std::vector<Subscriber> subscribers;
|
||||
|
||||
void UpdatePublishers(std::span<const uint8_t> data);
|
||||
void UpdateSubscribers(std::span<const uint8_t> data);
|
||||
|
||||
210
ntcore/src/main/native/cpp/ntcore_meta.cpp
Normal file
210
ntcore/src/main/native/cpp/ntcore_meta.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/MessagePack.h>
|
||||
#include <wpi/mpack.h>
|
||||
|
||||
#include "ntcore_cpp.h"
|
||||
|
||||
using namespace mpack;
|
||||
|
||||
using namespace nt::meta;
|
||||
|
||||
static SubscriberOptions DecodeSubscriberOptions(mpack_reader_t& r) {
|
||||
SubscriberOptions options;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "topicsonly") {
|
||||
options.topicsOnly = mpack_expect_bool(&r);
|
||||
} else if (key == "all") {
|
||||
options.sendAll = mpack_expect_bool(&r);
|
||||
} else if (key == "periodic") {
|
||||
options.periodic = mpack_expect_float(&r);
|
||||
} else if (key == "prefix") {
|
||||
options.prefixMatch = mpack_expect_bool(&r);
|
||||
} else {
|
||||
// TODO: Save other options
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
return options;
|
||||
}
|
||||
|
||||
std::optional<std::vector<ClientPublisher>> nt::meta::DecodeClientPublishers(
|
||||
std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numPub = mpack_expect_array_max(&r, 1000);
|
||||
std::vector<ClientPublisher> publishers;
|
||||
publishers.reserve(numPub);
|
||||
for (uint32_t i = 0; i < numPub; ++i) {
|
||||
ClientPublisher pub;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "uid") {
|
||||
pub.uid = mpack_expect_i64(&r);
|
||||
} else if (key == "topic") {
|
||||
mpack_expect_str(&r, &pub.topic);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
publishers.emplace_back(std::move(pub));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) == mpack_ok) {
|
||||
return {std::move(publishers)};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::vector<ClientSubscriber>> nt::meta::DecodeClientSubscribers(
|
||||
std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numSub = mpack_expect_array_max(&r, 1000);
|
||||
std::vector<ClientSubscriber> subscribers;
|
||||
subscribers.reserve(numSub);
|
||||
for (uint32_t i = 0; i < numSub; ++i) {
|
||||
ClientSubscriber sub;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "uid") {
|
||||
sub.uid = mpack_expect_i64(&r);
|
||||
} else if (key == "topics") {
|
||||
uint32_t numPrefix = mpack_expect_array_max(&r, 100);
|
||||
sub.topics.reserve(numPrefix);
|
||||
for (uint32_t k = 0; k < numPrefix; ++k) {
|
||||
std::string val;
|
||||
if (mpack_expect_str(&r, &val) == mpack_ok) {
|
||||
sub.topics.emplace_back(std::move(val));
|
||||
}
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
} else if (key == "options") {
|
||||
sub.options = DecodeSubscriberOptions(r);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
subscribers.emplace_back(std::move(sub));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) == mpack_ok) {
|
||||
return {std::move(subscribers)};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::vector<TopicPublisher>> nt::meta::DecodeTopicPublishers(
|
||||
std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numPub = mpack_expect_array_max(&r, 1000);
|
||||
std::vector<TopicPublisher> publishers;
|
||||
publishers.reserve(numPub);
|
||||
for (uint32_t i = 0; i < numPub; ++i) {
|
||||
TopicPublisher pub;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "pubuid") {
|
||||
pub.pubuid = mpack_expect_i64(&r);
|
||||
} else if (key == "client") {
|
||||
mpack_expect_str(&r, &pub.client);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
publishers.emplace_back(std::move(pub));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) == mpack_ok) {
|
||||
return {std::move(publishers)};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::vector<TopicSubscriber>> nt::meta::DecodeTopicSubscribers(
|
||||
std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numSub = mpack_expect_array_max(&r, 1000);
|
||||
std::vector<TopicSubscriber> subscribers;
|
||||
subscribers.reserve(numSub);
|
||||
for (uint32_t i = 0; i < numSub; ++i) {
|
||||
TopicSubscriber sub;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "subuid") {
|
||||
sub.subuid = mpack_expect_i64(&r);
|
||||
} else if (key == "client") {
|
||||
mpack_expect_str(&r, &sub.client);
|
||||
} else if (key == "options") {
|
||||
sub.options = DecodeSubscriberOptions(r);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
subscribers.emplace_back(std::move(sub));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) == mpack_ok) {
|
||||
return {std::move(subscribers)};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::vector<Client>> nt::meta::DecodeClients(
|
||||
std::span<const uint8_t> data) {
|
||||
mpack_reader_t r;
|
||||
mpack_reader_init_data(&r, data);
|
||||
uint32_t numClients = mpack_expect_array_max(&r, 100);
|
||||
std::vector<Client> clients;
|
||||
clients.reserve(numClients);
|
||||
for (uint32_t i = 0; i < numClients; ++i) {
|
||||
Client client;
|
||||
uint32_t numMapElem = mpack_expect_map(&r);
|
||||
for (uint32_t j = 0; j < numMapElem; ++j) {
|
||||
std::string key;
|
||||
mpack_expect_str(&r, &key);
|
||||
if (key == "id") {
|
||||
mpack_expect_str(&r, &client.id);
|
||||
} else if (key == "conn") {
|
||||
mpack_expect_str(&r, &client.conn);
|
||||
} else if (key == "ver") {
|
||||
client.version = mpack_expect_u16(&r);
|
||||
} else {
|
||||
mpack_discard(&r);
|
||||
}
|
||||
}
|
||||
mpack_done_map(&r);
|
||||
clients.emplace_back(std::move(client));
|
||||
}
|
||||
mpack_done_array(&r);
|
||||
if (mpack_reader_destroy(&r) == mpack_ok) {
|
||||
return {std::move(clients)};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
138
ntcore/src/main/native/cpp/ntcore_meta_c.cpp
Normal file
138
ntcore/src/main/native/cpp/ntcore_meta_c.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "Value_internal.h"
|
||||
#include "ntcore_cpp.h"
|
||||
|
||||
using namespace nt;
|
||||
using namespace nt::meta;
|
||||
|
||||
static void ConvertToC(const SubscriberOptions& in,
|
||||
NT_Meta_SubscriberOptions* out) {
|
||||
out->periodic = in.periodic;
|
||||
out->topicsOnly = in.topicsOnly;
|
||||
out->sendAll = in.sendAll;
|
||||
out->prefixMatch = in.prefixMatch;
|
||||
}
|
||||
|
||||
static void ConvertToC(const TopicPublisher& in, NT_Meta_TopicPublisher* out) {
|
||||
ConvertToC(in.client, &out->client);
|
||||
out->pubuid = in.pubuid;
|
||||
}
|
||||
|
||||
static void ConvertToC(const TopicSubscriber& in,
|
||||
NT_Meta_TopicSubscriber* out) {
|
||||
ConvertToC(in.client, &out->client);
|
||||
out->subuid = in.subuid;
|
||||
ConvertToC(in.options, &out->options);
|
||||
}
|
||||
|
||||
static void ConvertToC(const ClientPublisher& in,
|
||||
NT_Meta_ClientPublisher* out) {
|
||||
out->uid = in.uid;
|
||||
ConvertToC(in.topic, &out->topic);
|
||||
}
|
||||
|
||||
static void ConvertToC(const ClientSubscriber& in,
|
||||
NT_Meta_ClientSubscriber* out) {
|
||||
out->uid = in.uid;
|
||||
out->topics = ConvertToC<NT_String>(in.topics, &out->topicsCount);
|
||||
ConvertToC(in.options, &out->options);
|
||||
}
|
||||
|
||||
static void ConvertToC(const Client& in, NT_Meta_Client* out) {
|
||||
ConvertToC(in.id, &out->id);
|
||||
ConvertToC(in.conn, &out->conn);
|
||||
out->version = in.version;
|
||||
}
|
||||
|
||||
template <typename O, typename I>
|
||||
static O* ConvertToC(const std::optional<std::vector<I>>& in, size_t* out_len) {
|
||||
if (in) {
|
||||
if (O* rv = ConvertToC<O>(*in, out_len)) {
|
||||
return rv;
|
||||
} else {
|
||||
return static_cast<O*>(wpi::safe_malloc(0)); // return non-NULL
|
||||
}
|
||||
} else {
|
||||
*out_len = 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct NT_Meta_TopicPublisher* NT_Meta_DecodeTopicPublishers(
|
||||
const uint8_t* data, size_t size, size_t* count) {
|
||||
return ConvertToC<NT_Meta_TopicPublisher>(DecodeTopicPublishers({data, size}),
|
||||
count);
|
||||
}
|
||||
|
||||
struct NT_Meta_TopicSubscriber* NT_Meta_DecodeTopicSubscribers(
|
||||
const uint8_t* data, size_t size, size_t* count) {
|
||||
return ConvertToC<NT_Meta_TopicSubscriber>(
|
||||
DecodeTopicSubscribers({data, size}), count);
|
||||
}
|
||||
|
||||
struct NT_Meta_ClientPublisher* NT_Meta_DecodeClientPublishers(
|
||||
const uint8_t* data, size_t size, size_t* count) {
|
||||
return ConvertToC<NT_Meta_ClientPublisher>(
|
||||
DecodeClientPublishers({data, size}), count);
|
||||
}
|
||||
|
||||
struct NT_Meta_ClientSubscriber* NT_Meta_DecodeClientSubscribers(
|
||||
const uint8_t* data, size_t size, size_t* count) {
|
||||
return ConvertToC<NT_Meta_ClientSubscriber>(
|
||||
DecodeClientSubscribers({data, size}), count);
|
||||
}
|
||||
|
||||
struct NT_Meta_Client* NT_Meta_DecodeClients(const uint8_t* data, size_t size,
|
||||
size_t* count) {
|
||||
return ConvertToC<NT_Meta_Client>(DecodeClients({data, size}), count);
|
||||
}
|
||||
|
||||
void NT_Meta_FreeTopicPublishers(struct NT_Meta_TopicPublisher* arr,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
std::free(arr[i].client.str);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_Meta_FreeTopicSubscribers(struct NT_Meta_TopicSubscriber* arr,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
std::free(arr[i].client.str);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_Meta_FreeClientPublishers(struct NT_Meta_ClientPublisher* arr,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
std::free(arr[i].topic.str);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_Meta_FreeClientSubscribers(struct NT_Meta_ClientSubscriber* arr,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
NT_FreeStringArray(arr[i].topics, arr[i].topicsCount);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_Meta_FreeClients(struct NT_Meta_Client* arr, size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
std::free(arr[i].id.str);
|
||||
std::free(arr[i].conn.str);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@@ -1702,6 +1702,170 @@ struct NT_String* NT_GetValueStringArray(const struct NT_Value* value,
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup ntcore_c_meta_api ntcore C meta-topic API
|
||||
*
|
||||
* Meta-topic decoders for C.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Subscriber options. Different from PubSubOptions in this reflects only
|
||||
* options that are sent over the network.
|
||||
*/
|
||||
struct NT_Meta_SubscriberOptions {
|
||||
double periodic;
|
||||
NT_Bool topicsOnly;
|
||||
NT_Bool sendAll;
|
||||
NT_Bool prefixMatch;
|
||||
};
|
||||
|
||||
/**
|
||||
* Topic publisher (as published via `$pub$<topic>`).
|
||||
*/
|
||||
struct NT_Meta_TopicPublisher {
|
||||
struct NT_String client;
|
||||
uint64_t pubuid;
|
||||
};
|
||||
|
||||
/**
|
||||
* Topic subscriber (as published via `$sub$<topic>`).
|
||||
*/
|
||||
struct NT_Meta_TopicSubscriber {
|
||||
struct NT_String client;
|
||||
uint64_t subuid;
|
||||
struct NT_Meta_SubscriberOptions options;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client publisher (as published via `$clientpub$<client>` or `$serverpub`).
|
||||
*/
|
||||
struct NT_Meta_ClientPublisher {
|
||||
int64_t uid;
|
||||
struct NT_String topic;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client subscriber (as published via `$clientsub$<client>` or `$serversub`).
|
||||
*/
|
||||
struct NT_Meta_ClientSubscriber {
|
||||
int64_t uid;
|
||||
size_t topicsCount;
|
||||
struct NT_String* topics;
|
||||
struct NT_Meta_SubscriberOptions options;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client (as published via `$clients`).
|
||||
*/
|
||||
struct NT_Meta_Client {
|
||||
struct NT_String id;
|
||||
struct NT_String conn;
|
||||
uint16_t version;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes `$pub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @param size size of data contents
|
||||
* @param count number of elements in returned array (output)
|
||||
* @return Array of TopicPublishers, or NULL on decoding error.
|
||||
*/
|
||||
struct NT_Meta_TopicPublisher* NT_Meta_DecodeTopicPublishers(
|
||||
const uint8_t* data, size_t size, size_t* count);
|
||||
|
||||
/**
|
||||
* Decodes `$sub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @param size size of data contents
|
||||
* @param count number of elements in returned array (output)
|
||||
* @return Array of TopicSubscribers, or NULL on decoding error.
|
||||
*/
|
||||
struct NT_Meta_TopicSubscriber* NT_Meta_DecodeTopicSubscribers(
|
||||
const uint8_t* data, size_t size, size_t* count);
|
||||
|
||||
/**
|
||||
* Decodes `$clientpub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @param size size of data contents
|
||||
* @param count number of elements in returned array (output)
|
||||
* @return Array of ClientPublishers, or NULL on decoding error.
|
||||
*/
|
||||
struct NT_Meta_ClientPublisher* NT_Meta_DecodeClientPublishers(
|
||||
const uint8_t* data, size_t size, size_t* count);
|
||||
|
||||
/**
|
||||
* Decodes `$clientsub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @param size size of data contents
|
||||
* @param count number of elements in returned array (output)
|
||||
* @return Array of ClientSubscribers, or NULL on decoding error.
|
||||
*/
|
||||
struct NT_Meta_ClientSubscriber* NT_Meta_DecodeClientSubscribers(
|
||||
const uint8_t* data, size_t size, size_t* count);
|
||||
|
||||
/**
|
||||
* Decodes `$clients` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @param size size of data contents
|
||||
* @param count number of elements in returned array (output)
|
||||
* @return Array of Clients, or NULL on decoding error.
|
||||
*/
|
||||
struct NT_Meta_Client* NT_Meta_DecodeClients(const uint8_t* data, size_t size,
|
||||
size_t* count);
|
||||
|
||||
/**
|
||||
* Frees an array of NT_Meta_TopicPublisher.
|
||||
*
|
||||
* @param arr pointer to the array to free
|
||||
* @param count size of the array to free
|
||||
*/
|
||||
void NT_Meta_FreeTopicPublishers(struct NT_Meta_TopicPublisher* arr,
|
||||
size_t count);
|
||||
|
||||
/**
|
||||
* Frees an array of NT_Meta_TopicSubscriber.
|
||||
*
|
||||
* @param arr pointer to the array to free
|
||||
* @param count size of the array to free
|
||||
*/
|
||||
void NT_Meta_FreeTopicSubscribers(struct NT_Meta_TopicSubscriber* arr,
|
||||
size_t count);
|
||||
|
||||
/**
|
||||
* Frees an array of NT_Meta_ClientPublisher.
|
||||
*
|
||||
* @param arr pointer to the array to free
|
||||
* @param count size of the array to free
|
||||
*/
|
||||
void NT_Meta_FreeClientPublishers(struct NT_Meta_ClientPublisher* arr,
|
||||
size_t count);
|
||||
|
||||
/**
|
||||
* Frees an array of NT_Meta_ClientSubscriber.
|
||||
*
|
||||
* @param arr pointer to the array to free
|
||||
* @param count size of the array to free
|
||||
*/
|
||||
void NT_Meta_FreeClientSubscribers(struct NT_Meta_ClientSubscriber* arr,
|
||||
size_t count);
|
||||
|
||||
/**
|
||||
* Frees an array of NT_Meta_Client.
|
||||
*
|
||||
* @param arr pointer to the array to free
|
||||
* @param count size of the array to free
|
||||
*/
|
||||
void NT_Meta_FreeClients(struct NT_Meta_Client* arr, size_t count);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -1294,4 +1294,119 @@ NT_Listener AddPolledLogger(NT_ListenerPoller poller, unsigned int min_level,
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* NetworkTables meta-topic decoding functions.
|
||||
*/
|
||||
namespace meta {
|
||||
|
||||
/**
|
||||
* @defgroup ntcore_cpp_meta_api ntcore C++ meta-topic API
|
||||
*
|
||||
* Meta-topic decoders for C++.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Subscriber options. Different from PubSubOptions in this reflects only
|
||||
* options that are sent over the network.
|
||||
*/
|
||||
struct SubscriberOptions {
|
||||
double periodic = 0.1;
|
||||
bool topicsOnly = false;
|
||||
bool sendAll = false;
|
||||
bool prefixMatch = false;
|
||||
// std::string otherStr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Topic publisher (as published via `$pub$<topic>`).
|
||||
*/
|
||||
struct TopicPublisher {
|
||||
std::string client;
|
||||
uint64_t pubuid = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Topic subscriber (as published via `$sub$<topic>`).
|
||||
*/
|
||||
struct TopicSubscriber {
|
||||
std::string client;
|
||||
uint64_t subuid = 0;
|
||||
SubscriberOptions options;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client publisher (as published via `$clientpub$<client>` or `$serverpub`).
|
||||
*/
|
||||
struct ClientPublisher {
|
||||
int64_t uid = -1;
|
||||
std::string topic;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client subscriber (as published via `$clientsub$<client>` or `$serversub`).
|
||||
*/
|
||||
struct ClientSubscriber {
|
||||
int64_t uid = -1;
|
||||
std::vector<std::string> topics;
|
||||
SubscriberOptions options;
|
||||
};
|
||||
|
||||
/**
|
||||
* Client (as published via `$clients`).
|
||||
*/
|
||||
struct Client {
|
||||
std::string id;
|
||||
std::string conn;
|
||||
uint16_t version = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes `$pub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @return Vector of TopicPublishers, or empty optional on decoding error.
|
||||
*/
|
||||
std::optional<std::vector<TopicPublisher>> DecodeTopicPublishers(
|
||||
std::span<const uint8_t> data);
|
||||
|
||||
/**
|
||||
* Decodes `$sub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @return Vector of TopicSubscribers, or empty optional on decoding error.
|
||||
*/
|
||||
std::optional<std::vector<TopicSubscriber>> DecodeTopicSubscribers(
|
||||
std::span<const uint8_t> data);
|
||||
|
||||
/**
|
||||
* Decodes `$clientpub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @return Vector of ClientPublishers, or empty optional on decoding error.
|
||||
*/
|
||||
std::optional<std::vector<ClientPublisher>> DecodeClientPublishers(
|
||||
std::span<const uint8_t> data);
|
||||
|
||||
/**
|
||||
* Decodes `$clientsub$<topic>` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @return Vector of ClientSubscribers, or empty optional on decoding error.
|
||||
*/
|
||||
std::optional<std::vector<ClientSubscriber>> DecodeClientSubscribers(
|
||||
std::span<const uint8_t> data);
|
||||
|
||||
/**
|
||||
* Decodes `$clients` meta-topic data.
|
||||
*
|
||||
* @param data data contents
|
||||
* @return Vector of Clients, or empty optional on decoding error.
|
||||
*/
|
||||
std::optional<std::vector<Client>> DecodeClients(std::span<const uint8_t> data);
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace meta
|
||||
} // namespace nt
|
||||
|
||||
@@ -131,6 +131,16 @@ NT_GetValueType
|
||||
NT_InitString
|
||||
NT_InitValue
|
||||
NT_IsConnected
|
||||
NT_Meta_DecodeClientPublishers
|
||||
NT_Meta_DecodeClientSubscribers
|
||||
NT_Meta_DecodeClients
|
||||
NT_Meta_DecodeTopicPublishers
|
||||
NT_Meta_DecodeTopicSubscribers
|
||||
NT_Meta_FreeClientPublishers
|
||||
NT_Meta_FreeClientSubscribers
|
||||
NT_Meta_FreeClients
|
||||
NT_Meta_FreeTopicPublishers
|
||||
NT_Meta_FreeTopicSubscribers
|
||||
NT_Now
|
||||
NT_Publish
|
||||
NT_PublishEx
|
||||
|
||||
Reference in New Issue
Block a user