mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[ntcore] Add API to get and set user data on NT_Topic (#8962)
Theres many uses where we need to attach data to a topic, and doing it this way can make it really easy and efficient.
This commit is contained in:
@@ -106,6 +106,22 @@ class LocalStorage final : public net::ILocalStorage {
|
||||
}
|
||||
}
|
||||
|
||||
void* GetTopicUserData(NT_Topic topicHandle) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
if (auto topic = m_impl.GetTopicByHandle(topicHandle)) {
|
||||
return topic->userData;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SetTopicUserData(NT_Topic topicHandle, void* userData) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
if (auto topic = m_impl.GetTopicByHandle(topicHandle)) {
|
||||
topic->userData = userData;
|
||||
}
|
||||
}
|
||||
|
||||
NT_Type GetTopicType(NT_Topic topicHandle) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
if (auto topic = m_impl.GetTopicByHandle(topicHandle)) {
|
||||
|
||||
@@ -100,6 +100,8 @@ struct LocalTopic {
|
||||
VectorSet<LocalEntry*> entries;
|
||||
VectorSet<NT_Listener> listeners;
|
||||
|
||||
void* userData{nullptr};
|
||||
|
||||
private:
|
||||
// update flags from properties
|
||||
void RefreshFlags();
|
||||
|
||||
@@ -274,6 +274,14 @@ void NT_GetTopicName(NT_Topic topic, struct WPI_String* name) {
|
||||
wpi::nt::ConvertToC(wpi::nt::GetTopicName(topic), name);
|
||||
}
|
||||
|
||||
void* NT_GetTopicUserData(NT_Topic topic) {
|
||||
return wpi::nt::GetTopicUserData(topic);
|
||||
}
|
||||
|
||||
void NT_SetTopicUserData(NT_Topic topic, void* userData) {
|
||||
wpi::nt::SetTopicUserData(topic, userData);
|
||||
}
|
||||
|
||||
NT_Type NT_GetTopicType(NT_Topic topic) {
|
||||
return wpi::nt::GetTopicType(topic);
|
||||
}
|
||||
|
||||
@@ -217,6 +217,19 @@ std::string GetTopicName(NT_Topic topic) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
void* GetTopicUserData(NT_Topic topic) {
|
||||
if (auto ii = InstanceImpl::GetTyped(topic, Handle::TOPIC)) {
|
||||
return ii->localStorage.GetTopicUserData(topic);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SetTopicUserData(NT_Topic topic, void* userData) {
|
||||
if (auto ii = InstanceImpl::GetTyped(topic, Handle::TOPIC)) {
|
||||
ii->localStorage.SetTopicUserData(topic, userData);
|
||||
}
|
||||
}
|
||||
|
||||
NT_Type GetTopicType(NT_Topic topic) {
|
||||
if (auto ii = InstanceImpl::GetTyped(topic, Handle::TOPIC)) {
|
||||
|
||||
@@ -60,6 +60,23 @@ class Topic {
|
||||
*/
|
||||
std::string GetName() const { return ::wpi::nt::GetTopicName(m_handle); }
|
||||
|
||||
/**
|
||||
* Gets the user data associated with the topic.
|
||||
*
|
||||
* @return User data pointer, or nullptr if no user data is associated.
|
||||
*/
|
||||
void* GetUserData() const { return ::wpi::nt::GetTopicUserData(m_handle); }
|
||||
|
||||
/**
|
||||
* Sets the user data associated with the topic. User data is not used by
|
||||
* ntcore and is for the user's convenience. It is not automatically freed.
|
||||
*
|
||||
* @param userData User data pointer to associate with the topic.
|
||||
*/
|
||||
void SetUserData(void* userData) {
|
||||
::wpi::nt::SetTopicUserData(m_handle, userData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the topic.
|
||||
*
|
||||
|
||||
@@ -654,6 +654,25 @@ NT_Topic NT_GetTopic(NT_Inst inst, const struct WPI_String* name);
|
||||
*/
|
||||
void NT_GetTopicName(NT_Topic topic, struct WPI_String* name);
|
||||
|
||||
/**
|
||||
* Gets the user data pointer for the specified topic.
|
||||
* Returns nullptr if the handle is invalid or no user data is associated.
|
||||
* The user data pointer is not used by ntcore and is for the caller's use.
|
||||
*
|
||||
* @param topic topic handle
|
||||
* @return User data pointer
|
||||
*/
|
||||
void* NT_GetTopicUserData(NT_Topic topic);
|
||||
|
||||
/**
|
||||
* Sets the user data pointer for the specified topic. The user data pointer
|
||||
* is not used by ntcore and is for the caller's use.
|
||||
*
|
||||
* @param topic topic handle
|
||||
* @param userData user data pointer to associate with the topic
|
||||
*/
|
||||
void NT_SetTopicUserData(NT_Topic topic, void* userData);
|
||||
|
||||
/**
|
||||
* Gets the type for the specified topic, or unassigned if non existent.
|
||||
*
|
||||
|
||||
@@ -647,6 +647,28 @@ NT_Topic GetTopic(NT_Inst inst, std::string_view name);
|
||||
*/
|
||||
std::string GetTopicName(NT_Topic topic);
|
||||
|
||||
/**
|
||||
* Gets the user data associated with the specified topic.
|
||||
* Returns nullptr if the handle is invalid or no user data is associated.
|
||||
* User data is not used by ntcore and is for the user's convenience. It is not
|
||||
* inherited by subscribers/publishers of the topic, and is not automatically
|
||||
* freed.
|
||||
*
|
||||
* @param topic topic handle
|
||||
* @return User data pointer
|
||||
*/
|
||||
void* GetTopicUserData(NT_Topic topic);
|
||||
|
||||
/**
|
||||
* Sets the user data associated with the specified topic. User data is not
|
||||
* used by ntcore and is for the user's convenience. It is not inherited by
|
||||
* subscribers/publishers of the topic, and is not automatically freed.
|
||||
*
|
||||
* @param topic topic handle
|
||||
* @param userData User data pointer to associate with the topic
|
||||
*/
|
||||
void SetTopicUserData(NT_Topic topic, void* userData);
|
||||
|
||||
/**
|
||||
* Gets the type for the specified topic, or unassigned if non existent.
|
||||
*
|
||||
|
||||
@@ -15,6 +15,10 @@ classes:
|
||||
ignore: true
|
||||
GetInstance:
|
||||
GetName:
|
||||
GetUserData:
|
||||
ignore: true
|
||||
SetUserData:
|
||||
ignore: true
|
||||
GetType:
|
||||
GetTypeString:
|
||||
SetPersistent:
|
||||
|
||||
60
ntcore/src/test/native/cpp/TopicTest.cpp
Normal file
60
ntcore/src/test/native/cpp/TopicTest.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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 "wpi/nt/Topic.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "wpi/nt/NetworkTableInstance.hpp"
|
||||
|
||||
class TopicTest : public ::testing::Test {
|
||||
public:
|
||||
TopicTest() : m_inst{wpi::nt::NetworkTableInstance::Create()} {}
|
||||
~TopicTest() override { wpi::nt::NetworkTableInstance::Destroy(m_inst); }
|
||||
|
||||
protected:
|
||||
wpi::nt::NetworkTableInstance m_inst;
|
||||
};
|
||||
|
||||
TEST_F(TopicTest, UserDataDefaultsToNull) {
|
||||
auto topic = m_inst.GetTopic("foo");
|
||||
|
||||
EXPECT_EQ(nullptr, topic.GetUserData());
|
||||
}
|
||||
|
||||
TEST_F(TopicTest, UserDataRoundTrip) {
|
||||
auto topic = m_inst.GetTopic("foo");
|
||||
int data = 5;
|
||||
|
||||
topic.SetUserData(&data);
|
||||
|
||||
EXPECT_EQ(&data, topic.GetUserData());
|
||||
}
|
||||
|
||||
TEST_F(TopicTest, UserDataCanBeReplacedAndCleared) {
|
||||
auto topic = m_inst.GetTopic("foo");
|
||||
auto sameTopic = m_inst.GetTopic("foo");
|
||||
int data1 = 5;
|
||||
int data2 = 10;
|
||||
|
||||
topic.SetUserData(&data1);
|
||||
EXPECT_EQ(&data1, sameTopic.GetUserData());
|
||||
|
||||
sameTopic.SetUserData(&data2);
|
||||
EXPECT_EQ(&data2, topic.GetUserData());
|
||||
|
||||
topic.SetUserData(nullptr);
|
||||
EXPECT_EQ(nullptr, sameTopic.GetUserData());
|
||||
}
|
||||
|
||||
TEST_F(TopicTest, UserDataInvalidTopic) {
|
||||
wpi::nt::Topic topic;
|
||||
int data = 5;
|
||||
|
||||
EXPECT_EQ(nullptr, topic.GetUserData());
|
||||
|
||||
topic.SetUserData(&data);
|
||||
|
||||
EXPECT_EQ(nullptr, topic.GetUserData());
|
||||
}
|
||||
Reference in New Issue
Block a user