From 4c83259acb509693be14e9b6c273ca16b2b2e95a Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 19 Sep 2015 12:18:25 -0700 Subject: [PATCH] C++ NetworkTable: Provide AddSubTableListener(). This matches the implementation provided by Java NetworkTable, with the exception that the subtable is not provided (because it's not a value). The listener still can get access to the subtable by calling source->getSubTable(key). --- include/networktables/NetworkTable.h | 1 + include/tables/ITable.h | 6 ++++++ src/networktables/NetworkTable.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/include/networktables/NetworkTable.h b/include/networktables/NetworkTable.h index 76309f7a9f..fbaf906dea 100644 --- a/include/networktables/NetworkTable.h +++ b/include/networktables/NetworkTable.h @@ -139,6 +139,7 @@ class NetworkTable : public ITable { void AddTableListener(ITableListener* listener, bool immediateNotify); void AddTableListener(llvm::StringRef key, ITableListener* listener, bool immediateNotify); + void AddSubTableListener(ITableListener* listener); void RemoveTableListener(ITableListener* listener); /** diff --git a/include/tables/ITable.h b/include/tables/ITable.h index 73eb1d83d9..cb1a0ddad0 100644 --- a/include/tables/ITable.h +++ b/include/tables/ITable.h @@ -220,6 +220,12 @@ class ITable { virtual void AddTableListener(llvm::StringRef key, ITableListener* listener, bool immediateNotify) = 0; + /** + * This will immediately notify the listener of all current sub tables + * @param listener the listener to add + */ + virtual void AddSubTableListener(ITableListener* listener) = 0; + /** * Remove a listener from receiving table events * diff --git a/src/networktables/NetworkTable.cpp b/src/networktables/NetworkTable.cpp index ddfa0c928e..33bbb32f0d 100644 --- a/src/networktables/NetworkTable.cpp +++ b/src/networktables/NetworkTable.cpp @@ -3,6 +3,7 @@ #include #include "llvm/SmallString.h" +#include "llvm/StringMap.h" #include "tables/ITableListener.h" #include "ntcore.h" @@ -136,6 +137,33 @@ void NetworkTable::AddTableListener(StringRef key, m_listeners.emplace_back(listener, id); } +void NetworkTable::AddSubTableListener(ITableListener* listener) { + std::lock_guard lock(m_mutex); + llvm::SmallString<128> path(m_path); + path += PATH_SEPARATOR_CHAR; + std::size_t prefix_len = path.size(); + + // The lambda needs to be copyable, but StringMap is not, so use + // a shared_ptr to it. + auto notified_tables = std::make_shared>(); + + unsigned int id = nt::AddEntryListener( + path, + [=](unsigned int uid, StringRef name, std::shared_ptr value, + bool is_new) mutable { + StringRef relative_key = name.substr(prefix_len); + auto end_sub_table = relative_key.find(PATH_SEPARATOR_CHAR); + if (end_sub_table == StringRef::npos) return; + StringRef sub_table_key = relative_key.substr(0, end_sub_table); + if (notified_tables->find(sub_table_key) == notified_tables->end()) + return; + notified_tables->insert(std::make_pair(sub_table_key, '\0')); + listener->ValueChanged(this, sub_table_key, nullptr, true); + }, + true); + m_listeners.emplace_back(listener, id); +} + void NetworkTable::RemoveTableListener(ITableListener* listener) { std::lock_guard lock(m_mutex); auto matches_begin =