mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
Add braces to C++ single-line loops and conditionals (NFC) (#2973)
This makes code easier to read and more consistent between C++ and Java. Also update clang-format settings to always add a line break (even if no braces are used).
This commit is contained in:
@@ -57,7 +57,9 @@ class CallbackThread : public wpi::SafeThread {
|
||||
~CallbackThread() {
|
||||
// Wake up any blocked pollers
|
||||
for (size_t i = 0; i < m_pollers.size(); ++i) {
|
||||
if (auto poller = m_pollers[i]) poller->Terminate();
|
||||
if (auto poller = m_pollers[i]) {
|
||||
poller->Terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,9 +89,13 @@ class CallbackThread : public wpi::SafeThread {
|
||||
// Must be called with m_mutex held
|
||||
template <typename... Args>
|
||||
void SendPoller(unsigned int poller_uid, Args&&... args) {
|
||||
if (poller_uid > m_pollers.size()) return;
|
||||
if (poller_uid > m_pollers.size()) {
|
||||
return;
|
||||
}
|
||||
auto poller = m_pollers[poller_uid];
|
||||
if (!poller) return;
|
||||
if (!poller) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::scoped_lock lock(poller->poll_mutex);
|
||||
poller->poll_queue.emplace(std::forward<Args>(args)...);
|
||||
@@ -105,11 +111,15 @@ void CallbackThread<Derived, TUserInfo, TListenerData, TNotifierData>::Main() {
|
||||
while (m_active) {
|
||||
while (m_queue.empty()) {
|
||||
m_cond.wait(lock);
|
||||
if (!m_active) return;
|
||||
if (!m_active) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (!m_queue.empty()) {
|
||||
if (!m_active) return;
|
||||
if (!m_active) {
|
||||
return;
|
||||
}
|
||||
auto item = std::move(m_queue.front());
|
||||
|
||||
if (item.first != UINT_MAX) {
|
||||
@@ -132,9 +142,12 @@ void CallbackThread<Derived, TUserInfo, TListenerData, TNotifierData>::Main() {
|
||||
// Use index because iterator might get invalidated.
|
||||
for (size_t i = 0; i < m_listeners.size(); ++i) {
|
||||
auto& listener = m_listeners[i];
|
||||
if (!listener) continue;
|
||||
if (!static_cast<Derived*>(this)->Matches(listener, item.second))
|
||||
if (!listener) {
|
||||
continue;
|
||||
}
|
||||
if (!static_cast<Derived*>(this)->Matches(listener, item.second)) {
|
||||
continue;
|
||||
}
|
||||
static_cast<Derived*>(this)->SetListener(&item.second,
|
||||
static_cast<unsigned>(i));
|
||||
if (listener.callback) {
|
||||
@@ -171,7 +184,9 @@ class CallbackManager {
|
||||
|
||||
void Remove(unsigned int listener_uid) {
|
||||
auto thr = m_owner.GetThread();
|
||||
if (!thr) return;
|
||||
if (!thr) {
|
||||
return;
|
||||
}
|
||||
thr->m_listeners.erase(listener_uid);
|
||||
}
|
||||
|
||||
@@ -184,37 +199,52 @@ class CallbackManager {
|
||||
|
||||
void RemovePoller(unsigned int poller_uid) {
|
||||
auto thr = m_owner.GetThread();
|
||||
if (!thr) return;
|
||||
if (!thr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any listeners that are associated with this poller
|
||||
for (size_t i = 0; i < thr->m_listeners.size(); ++i) {
|
||||
if (thr->m_listeners[i].poller_uid == poller_uid)
|
||||
if (thr->m_listeners[i].poller_uid == poller_uid) {
|
||||
thr->m_listeners.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake up any blocked pollers
|
||||
if (poller_uid >= thr->m_pollers.size()) return;
|
||||
if (poller_uid >= thr->m_pollers.size()) {
|
||||
return;
|
||||
}
|
||||
auto poller = thr->m_pollers[poller_uid];
|
||||
if (!poller) return;
|
||||
if (!poller) {
|
||||
return;
|
||||
}
|
||||
poller->Terminate();
|
||||
return thr->m_pollers.erase(poller_uid);
|
||||
}
|
||||
|
||||
bool WaitForQueue(double timeout) {
|
||||
auto thr = m_owner.GetThread();
|
||||
if (!thr) return true;
|
||||
if (!thr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& lock = thr.GetLock();
|
||||
auto timeout_time = std::chrono::steady_clock::now() +
|
||||
std::chrono::duration<double>(timeout);
|
||||
while (!thr->m_queue.empty()) {
|
||||
if (!thr->m_active) return true;
|
||||
if (timeout == 0) return false;
|
||||
if (!thr->m_active) {
|
||||
return true;
|
||||
}
|
||||
if (timeout == 0) {
|
||||
return false;
|
||||
}
|
||||
if (timeout < 0) {
|
||||
thr->m_queue_empty.wait(lock);
|
||||
} else {
|
||||
auto cond_timed_out = thr->m_queue_empty.wait_until(lock, timeout_time);
|
||||
if (cond_timed_out == std::cv_status::timeout) return false;
|
||||
if (cond_timed_out == std::cv_status::timeout) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,10 +262,16 @@ class CallbackManager {
|
||||
std::shared_ptr<typename Thread::Poller> poller;
|
||||
{
|
||||
auto thr = m_owner.GetThread();
|
||||
if (!thr) return infos;
|
||||
if (poller_uid > thr->m_pollers.size()) return infos;
|
||||
if (!thr) {
|
||||
return infos;
|
||||
}
|
||||
if (poller_uid > thr->m_pollers.size()) {
|
||||
return infos;
|
||||
}
|
||||
poller = thr->m_pollers[poller_uid];
|
||||
if (!poller) return infos;
|
||||
if (!poller) {
|
||||
return infos;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_lock lock(poller->poll_mutex);
|
||||
@@ -243,7 +279,9 @@ class CallbackManager {
|
||||
std::chrono::duration<double>(timeout);
|
||||
*timed_out = false;
|
||||
while (poller->poll_queue.empty()) {
|
||||
if (poller->terminating) return infos;
|
||||
if (poller->terminating) {
|
||||
return infos;
|
||||
}
|
||||
if (poller->canceling) {
|
||||
// Note: this only works if there's a single thread calling this
|
||||
// function for any particular poller, but that's the intended use.
|
||||
@@ -276,10 +314,16 @@ class CallbackManager {
|
||||
std::shared_ptr<typename Thread::Poller> poller;
|
||||
{
|
||||
auto thr = m_owner.GetThread();
|
||||
if (!thr) return;
|
||||
if (poller_uid > thr->m_pollers.size()) return;
|
||||
if (!thr) {
|
||||
return;
|
||||
}
|
||||
if (poller_uid > thr->m_pollers.size()) {
|
||||
return;
|
||||
}
|
||||
poller = thr->m_pollers[poller_uid];
|
||||
if (!poller) return;
|
||||
if (!poller) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -305,7 +349,9 @@ class CallbackManager {
|
||||
template <typename... Args>
|
||||
void Send(unsigned int only_listener, Args&&... args) {
|
||||
auto thr = m_owner.GetThread();
|
||||
if (!thr || thr->m_listeners.empty()) return;
|
||||
if (!thr || thr->m_listeners.empty()) {
|
||||
return;
|
||||
}
|
||||
thr->m_queue.emplace(std::piecewise_construct,
|
||||
std::make_tuple(only_listener),
|
||||
std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
|
||||
@@ -8,7 +8,9 @@ using namespace nt;
|
||||
|
||||
ConnectionNotifier::ConnectionNotifier(int inst) : m_inst(inst) {}
|
||||
|
||||
void ConnectionNotifier::Start() { DoStart(m_inst); }
|
||||
void ConnectionNotifier::Start() {
|
||||
DoStart(m_inst);
|
||||
}
|
||||
|
||||
unsigned int ConnectionNotifier::Add(
|
||||
std::function<void(const ConnectionNotification& event)> callback) {
|
||||
|
||||
@@ -38,14 +38,16 @@ void Dispatcher::SetServer(const char* server_name, unsigned int port) {
|
||||
void Dispatcher::SetServer(
|
||||
ArrayRef<std::pair<StringRef, unsigned int>> servers) {
|
||||
wpi::SmallVector<std::pair<std::string, int>, 16> servers_copy;
|
||||
for (const auto& server : servers)
|
||||
for (const auto& server : servers) {
|
||||
servers_copy.emplace_back(std::string{server.first.trim()},
|
||||
static_cast<int>(server.second));
|
||||
}
|
||||
|
||||
SetConnector([=]() -> std::unique_ptr<wpi::NetworkStream> {
|
||||
wpi::SmallVector<std::pair<const char*, int>, 16> servers_copy2;
|
||||
for (const auto& server : servers_copy)
|
||||
for (const auto& server : servers_copy) {
|
||||
servers_copy2.emplace_back(server.first.c_str(), server.second);
|
||||
}
|
||||
return wpi::TCPConnector::connect_parallel(servers_copy2, m_logger, 1);
|
||||
});
|
||||
}
|
||||
@@ -100,7 +102,9 @@ void Dispatcher::SetServerOverride(const char* server_name, unsigned int port) {
|
||||
});
|
||||
}
|
||||
|
||||
void Dispatcher::ClearServerOverride() { ClearConnectorOverride(); }
|
||||
void Dispatcher::ClearServerOverride() {
|
||||
ClearConnectorOverride();
|
||||
}
|
||||
|
||||
DispatcherBase::DispatcherBase(IStorage& storage, IConnectionNotifier& notifier,
|
||||
wpi::Logger& logger)
|
||||
@@ -109,14 +113,20 @@ DispatcherBase::DispatcherBase(IStorage& storage, IConnectionNotifier& notifier,
|
||||
m_update_rate = 100;
|
||||
}
|
||||
|
||||
DispatcherBase::~DispatcherBase() { Stop(); }
|
||||
DispatcherBase::~DispatcherBase() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
unsigned int DispatcherBase::GetNetworkMode() const { return m_networkMode; }
|
||||
unsigned int DispatcherBase::GetNetworkMode() const {
|
||||
return m_networkMode;
|
||||
}
|
||||
|
||||
void DispatcherBase::StartLocal() {
|
||||
{
|
||||
std::scoped_lock lock(m_user_mutex);
|
||||
if (m_active) return;
|
||||
if (m_active) {
|
||||
return;
|
||||
}
|
||||
m_active = true;
|
||||
}
|
||||
m_networkMode = NT_NET_MODE_LOCAL;
|
||||
@@ -128,7 +138,9 @@ void DispatcherBase::StartServer(
|
||||
std::unique_ptr<wpi::NetworkAcceptor> acceptor) {
|
||||
{
|
||||
std::scoped_lock lock(m_user_mutex);
|
||||
if (m_active) return;
|
||||
if (m_active) {
|
||||
return;
|
||||
}
|
||||
m_active = true;
|
||||
}
|
||||
m_networkMode = NT_NET_MODE_SERVER | NT_NET_MODE_STARTING;
|
||||
@@ -160,7 +172,9 @@ void DispatcherBase::StartServer(
|
||||
void DispatcherBase::StartClient() {
|
||||
{
|
||||
std::scoped_lock lock(m_user_mutex);
|
||||
if (m_active) return;
|
||||
if (m_active) {
|
||||
return;
|
||||
}
|
||||
m_active = true;
|
||||
}
|
||||
m_networkMode = NT_NET_MODE_CLIENT | NT_NET_MODE_STARTING;
|
||||
@@ -184,11 +198,17 @@ void DispatcherBase::Stop() {
|
||||
ClientReconnect();
|
||||
|
||||
// wake up server thread by shutting down the socket
|
||||
if (m_server_acceptor) m_server_acceptor->shutdown();
|
||||
if (m_server_acceptor) {
|
||||
m_server_acceptor->shutdown();
|
||||
}
|
||||
|
||||
// join threads, with timeout
|
||||
if (m_dispatch_thread.joinable()) m_dispatch_thread.join();
|
||||
if (m_clientserver_thread.joinable()) m_clientserver_thread.join();
|
||||
if (m_dispatch_thread.joinable()) {
|
||||
m_dispatch_thread.join();
|
||||
}
|
||||
if (m_clientserver_thread.joinable()) {
|
||||
m_clientserver_thread.join();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<INetworkConnection>> conns;
|
||||
{
|
||||
@@ -202,10 +222,11 @@ void DispatcherBase::Stop() {
|
||||
|
||||
void DispatcherBase::SetUpdateRate(double interval) {
|
||||
// don't allow update rates faster than 5 ms or slower than 1 second
|
||||
if (interval < 0.005)
|
||||
if (interval < 0.005) {
|
||||
interval = 0.005;
|
||||
else if (interval > 1.0)
|
||||
} else if (interval > 1.0) {
|
||||
interval = 1.0;
|
||||
}
|
||||
m_update_rate = static_cast<unsigned int>(interval * 1000);
|
||||
}
|
||||
|
||||
@@ -219,7 +240,9 @@ void DispatcherBase::Flush() {
|
||||
{
|
||||
std::scoped_lock lock(m_flush_mutex);
|
||||
// don't allow flushes more often than every 5 ms
|
||||
if ((now - m_last_flush) < 5000) return;
|
||||
if ((now - m_last_flush) < 5000) {
|
||||
return;
|
||||
}
|
||||
m_last_flush = now;
|
||||
m_do_flush = true;
|
||||
}
|
||||
@@ -228,11 +251,15 @@ void DispatcherBase::Flush() {
|
||||
|
||||
std::vector<ConnectionInfo> DispatcherBase::GetConnections() const {
|
||||
std::vector<ConnectionInfo> conns;
|
||||
if (!m_active) return conns;
|
||||
if (!m_active) {
|
||||
return conns;
|
||||
}
|
||||
|
||||
std::scoped_lock lock(m_user_mutex);
|
||||
for (auto& conn : m_connections) {
|
||||
if (conn->state() != NetworkConnection::kActive) continue;
|
||||
if (conn->state() != NetworkConnection::kActive) {
|
||||
continue;
|
||||
}
|
||||
conns.emplace_back(conn->info());
|
||||
}
|
||||
|
||||
@@ -240,13 +267,19 @@ std::vector<ConnectionInfo> DispatcherBase::GetConnections() const {
|
||||
}
|
||||
|
||||
bool DispatcherBase::IsConnected() const {
|
||||
if (!m_active) return false;
|
||||
if (!m_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_networkMode == NT_NET_MODE_LOCAL) return true;
|
||||
if (m_networkMode == NT_NET_MODE_LOCAL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::scoped_lock lock(m_user_mutex);
|
||||
for (auto& conn : m_connections) {
|
||||
if (conn->state() == NetworkConnection::kActive) return true;
|
||||
if (conn->state() == NetworkConnection::kActive) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -260,7 +293,9 @@ unsigned int DispatcherBase::AddListener(
|
||||
// perform immediate notifications
|
||||
if (immediate_notify) {
|
||||
for (auto& conn : m_connections) {
|
||||
if (conn->state() != NetworkConnection::kActive) continue;
|
||||
if (conn->state() != NetworkConnection::kActive) {
|
||||
continue;
|
||||
}
|
||||
m_notifier.NotifyConnection(true, conn->info(), uid);
|
||||
}
|
||||
}
|
||||
@@ -274,7 +309,9 @@ unsigned int DispatcherBase::AddPolledListener(unsigned int poller_uid,
|
||||
// perform immediate notifications
|
||||
if (immediate_notify) {
|
||||
for (auto& conn : m_connections) {
|
||||
if (conn->state() != NetworkConnection::kActive) continue;
|
||||
if (conn->state() != NetworkConnection::kActive) {
|
||||
continue;
|
||||
}
|
||||
m_notifier.NotifyConnection(true, conn->info(), uid);
|
||||
}
|
||||
}
|
||||
@@ -307,7 +344,9 @@ void DispatcherBase::DispatchThreadMain() {
|
||||
while (m_active) {
|
||||
// handle loop taking too long
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
if (start > timeout_time) timeout_time = start;
|
||||
if (start > timeout_time) {
|
||||
timeout_time = start;
|
||||
}
|
||||
|
||||
// wait for periodic or when flushed
|
||||
timeout_time += std::chrono::milliseconds(m_update_rate);
|
||||
@@ -316,16 +355,22 @@ void DispatcherBase::DispatchThreadMain() {
|
||||
[&] { return !m_active || m_do_flush; });
|
||||
m_do_flush = false;
|
||||
flush_lock.unlock();
|
||||
if (!m_active) break; // in case we were woken up to terminate
|
||||
if (!m_active) {
|
||||
break; // in case we were woken up to terminate
|
||||
}
|
||||
|
||||
// perform periodic persistent save
|
||||
if ((m_networkMode & NT_NET_MODE_SERVER) != 0 &&
|
||||
!m_persist_filename.empty() && start > next_save_time) {
|
||||
next_save_time += save_delta_time;
|
||||
// handle loop taking too long
|
||||
if (start > next_save_time) next_save_time = start + save_delta_time;
|
||||
if (start > next_save_time) {
|
||||
next_save_time = start + save_delta_time;
|
||||
}
|
||||
const char* err = m_storage.SavePersistent(m_persist_filename, true);
|
||||
if (err) WARNING("periodic persistent save: " << err);
|
||||
if (err) {
|
||||
WARNING("periodic persistent save: " << err);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -340,13 +385,15 @@ void DispatcherBase::DispatchThreadMain() {
|
||||
for (auto& conn : m_connections) {
|
||||
// post outgoing messages if connection is active
|
||||
// only send keep-alives on client
|
||||
if (conn->state() == NetworkConnection::kActive)
|
||||
if (conn->state() == NetworkConnection::kActive) {
|
||||
conn->PostOutgoing((m_networkMode & NT_NET_MODE_CLIENT) != 0);
|
||||
}
|
||||
|
||||
// if client, reconnect if connection died
|
||||
if ((m_networkMode & NT_NET_MODE_CLIENT) != 0 &&
|
||||
conn->state() == NetworkConnection::kDead)
|
||||
conn->state() == NetworkConnection::kDead) {
|
||||
reconnect = true;
|
||||
}
|
||||
}
|
||||
// reconnect if we disconnected (and a reconnect is not in progress)
|
||||
if (reconnect && !m_do_reconnect) {
|
||||
@@ -362,12 +409,17 @@ void DispatcherBase::QueueOutgoing(std::shared_ptr<Message> msg,
|
||||
INetworkConnection* except) {
|
||||
std::scoped_lock user_lock(m_user_mutex);
|
||||
for (auto& conn : m_connections) {
|
||||
if (conn.get() == except) continue;
|
||||
if (only && conn.get() != only) continue;
|
||||
if (conn.get() == except) {
|
||||
continue;
|
||||
}
|
||||
if (only && conn.get() != only) {
|
||||
continue;
|
||||
}
|
||||
auto state = conn->state();
|
||||
if (state != NetworkConnection::kSynchronized &&
|
||||
state != NetworkConnection::kActive)
|
||||
state != NetworkConnection::kActive) {
|
||||
continue;
|
||||
}
|
||||
conn->QueueOutgoing(msg);
|
||||
}
|
||||
}
|
||||
@@ -412,7 +464,9 @@ void DispatcherBase::ServerThreadMain() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!placed) m_connections.emplace_back(conn);
|
||||
if (!placed) {
|
||||
m_connections.emplace_back(conn);
|
||||
}
|
||||
conn->Start();
|
||||
}
|
||||
}
|
||||
@@ -496,16 +550,22 @@ bool DispatcherBase::ClientHandshake(
|
||||
}
|
||||
|
||||
if (msg->Is(Message::kProtoUnsup)) {
|
||||
if (msg->id() == 0x0200) ClientReconnect(0x0200);
|
||||
if (msg->id() == 0x0200) {
|
||||
ClientReconnect(0x0200);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool new_server = true;
|
||||
if (conn.proto_rev() >= 0x0300) {
|
||||
// should be server hello; if not, disconnect.
|
||||
if (!msg->Is(Message::kServerHello)) return false;
|
||||
if (!msg->Is(Message::kServerHello)) {
|
||||
return false;
|
||||
}
|
||||
conn.set_remote_id(msg->str());
|
||||
if ((msg->flags() & 1) != 0) new_server = false;
|
||||
if ((msg->flags() & 1) != 0) {
|
||||
new_server = false;
|
||||
}
|
||||
// get the next message
|
||||
msg = get_msg();
|
||||
}
|
||||
@@ -520,7 +580,9 @@ bool DispatcherBase::ClientHandshake(
|
||||
}
|
||||
DEBUG4("received init str=" << msg->str() << " id=" << msg->id()
|
||||
<< " seq_num=" << msg->seq_num_uid());
|
||||
if (msg->Is(Message::kServerHelloDone)) break;
|
||||
if (msg->Is(Message::kServerHelloDone)) {
|
||||
break;
|
||||
}
|
||||
// shouldn't receive a keep alive, but handle gracefully
|
||||
if (msg->Is(Message::kKeepAlive)) {
|
||||
msg = get_msg();
|
||||
@@ -543,10 +605,13 @@ bool DispatcherBase::ClientHandshake(
|
||||
|
||||
m_storage.ApplyInitialAssignments(conn, incoming, new_server, &outgoing);
|
||||
|
||||
if (conn.proto_rev() >= 0x0300)
|
||||
if (conn.proto_rev() >= 0x0300) {
|
||||
outgoing.emplace_back(Message::ClientHelloDone());
|
||||
}
|
||||
|
||||
if (!outgoing.empty()) send_msgs(outgoing);
|
||||
if (!outgoing.empty()) {
|
||||
send_msgs(outgoing);
|
||||
}
|
||||
|
||||
INFO("client: CONNECTED to server " << conn.stream().getPeerIP() << " port "
|
||||
<< conn.stream().getPeerPort());
|
||||
@@ -575,7 +640,9 @@ bool DispatcherBase::ServerHandshake(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (proto_rev >= 0x0300) conn.set_remote_id(msg->str());
|
||||
if (proto_rev >= 0x0300) {
|
||||
conn.set_remote_id(msg->str());
|
||||
}
|
||||
|
||||
// Set the proto version to the client requested version
|
||||
DEBUG0("server: client protocol " << proto_rev);
|
||||
@@ -614,7 +681,9 @@ bool DispatcherBase::ServerHandshake(
|
||||
DEBUG0("server: disconnected waiting for initial entries");
|
||||
return false;
|
||||
}
|
||||
if (msg->Is(Message::kClientHelloDone)) break;
|
||||
if (msg->Is(Message::kClientHelloDone)) {
|
||||
break;
|
||||
}
|
||||
// shouldn't receive a keep alive, but handle gracefully
|
||||
if (msg->Is(Message::kKeepAlive)) {
|
||||
msg = get_msg();
|
||||
@@ -631,8 +700,9 @@ bool DispatcherBase::ServerHandshake(
|
||||
// get the next message (blocks)
|
||||
msg = get_msg();
|
||||
}
|
||||
for (auto& msg : incoming)
|
||||
for (auto& msg : incoming) {
|
||||
m_storage.ProcessIncoming(msg, &conn, std::weak_ptr<NetworkConnection>());
|
||||
}
|
||||
}
|
||||
|
||||
INFO("server: client CONNECTED: " << conn.stream().getPeerIP() << " port "
|
||||
@@ -641,7 +711,9 @@ bool DispatcherBase::ServerHandshake(
|
||||
}
|
||||
|
||||
void DispatcherBase::ClientReconnect(unsigned int proto_rev) {
|
||||
if ((m_networkMode & NT_NET_MODE_SERVER) != 0) return;
|
||||
if ((m_networkMode & NT_NET_MODE_SERVER) != 0) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::scoped_lock lock(m_user_mutex);
|
||||
m_reconnect_proto_rev = proto_rev;
|
||||
|
||||
@@ -32,10 +32,11 @@ DsClient::DsClient(Dispatcher& dispatcher, wpi::Logger& logger)
|
||||
|
||||
void DsClient::Start(unsigned int port) {
|
||||
auto thr = m_owner.GetThread();
|
||||
if (!thr)
|
||||
if (!thr) {
|
||||
m_owner.Start(m_dispatcher, m_logger, port);
|
||||
else
|
||||
} else {
|
||||
thr->m_port = port;
|
||||
}
|
||||
}
|
||||
|
||||
void DsClient::Stop() {
|
||||
@@ -44,7 +45,9 @@ void DsClient::Stop() {
|
||||
auto thr = m_owner.GetThread();
|
||||
if (thr) {
|
||||
thr->m_active = false;
|
||||
if (thr->m_stream) thr->m_stream->close();
|
||||
if (thr->m_stream) {
|
||||
thr->m_stream->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
m_owner.Stop();
|
||||
@@ -64,12 +67,18 @@ void DsClient::Thread::Main() {
|
||||
m_cond.wait_until(lock, timeout_time, [&] { return !m_active; });
|
||||
port = m_port;
|
||||
}
|
||||
if (!m_active) goto done;
|
||||
if (!m_active) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Try to connect to DS on the local machine
|
||||
m_stream = wpi::TCPConnector::connect("127.0.0.1", 1742, nolog, 1);
|
||||
if (!m_active) goto done;
|
||||
if (!m_stream) continue;
|
||||
if (!m_active) {
|
||||
goto done;
|
||||
}
|
||||
if (!m_stream) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG3("connected to DS");
|
||||
wpi::raw_socket_istream is(*m_stream);
|
||||
@@ -83,8 +92,12 @@ void DsClient::Thread::Main() {
|
||||
// Throw away characters until {
|
||||
do {
|
||||
is.read(ch);
|
||||
if (is.has_error()) break;
|
||||
if (!m_active) goto done;
|
||||
if (is.has_error()) {
|
||||
break;
|
||||
}
|
||||
if (!m_active) {
|
||||
goto done;
|
||||
}
|
||||
} while (ch != '{');
|
||||
json += '{';
|
||||
|
||||
@@ -96,8 +109,12 @@ void DsClient::Thread::Main() {
|
||||
// Read characters until }
|
||||
do {
|
||||
is.read(ch);
|
||||
if (is.has_error()) break;
|
||||
if (!m_active) goto done;
|
||||
if (is.has_error()) {
|
||||
break;
|
||||
}
|
||||
if (!m_active) {
|
||||
goto done;
|
||||
}
|
||||
json += ch;
|
||||
} while (ch != '}');
|
||||
|
||||
@@ -109,16 +126,22 @@ void DsClient::Thread::Main() {
|
||||
|
||||
// Look for "robotIP":12345, and get 12345 portion
|
||||
size_t pos = json.find("\"robotIP\"");
|
||||
if (pos == wpi::StringRef::npos) continue; // could not find?
|
||||
if (pos == wpi::StringRef::npos) {
|
||||
continue; // could not find?
|
||||
}
|
||||
pos += 9;
|
||||
pos = json.find(':', pos);
|
||||
if (pos == wpi::StringRef::npos) continue; // could not find?
|
||||
if (pos == wpi::StringRef::npos) {
|
||||
continue; // could not find?
|
||||
}
|
||||
size_t endpos = json.find_first_not_of("0123456789", pos + 1);
|
||||
DEBUG3("found robotIP=" << json.slice(pos + 1, endpos));
|
||||
|
||||
// Parse into number
|
||||
unsigned int ip = 0;
|
||||
if (json.slice(pos + 1, endpos).getAsInteger(10, ip)) continue; // error
|
||||
if (json.slice(pos + 1, endpos).getAsInteger(10, ip)) {
|
||||
continue; // error
|
||||
}
|
||||
|
||||
// If zero, clear the server override
|
||||
if (ip == 0) {
|
||||
@@ -128,7 +151,9 @@ void DsClient::Thread::Main() {
|
||||
}
|
||||
|
||||
// If unchanged, don't reconnect
|
||||
if (ip == oldip) continue;
|
||||
if (ip == oldip) {
|
||||
continue;
|
||||
}
|
||||
oldip = ip;
|
||||
|
||||
// Convert number into dotted quad
|
||||
|
||||
@@ -13,13 +13,19 @@ EntryNotifier::EntryNotifier(int inst, wpi::Logger& logger)
|
||||
m_local_notifiers = false;
|
||||
}
|
||||
|
||||
void EntryNotifier::Start() { DoStart(m_inst); }
|
||||
void EntryNotifier::Start() {
|
||||
DoStart(m_inst);
|
||||
}
|
||||
|
||||
bool EntryNotifier::local_notifiers() const { return m_local_notifiers; }
|
||||
bool EntryNotifier::local_notifiers() const {
|
||||
return m_local_notifiers;
|
||||
}
|
||||
|
||||
bool impl::EntryNotifierThread::Matches(const EntryListenerData& listener,
|
||||
const EntryNotification& data) {
|
||||
if (!data.value) return false;
|
||||
if (!data.value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flags must be within requested flag set for this listener.
|
||||
// Because assign messages can result in both a value and flags update,
|
||||
@@ -29,17 +35,24 @@ bool impl::EntryNotifierThread::Matches(const EntryListenerData& listener,
|
||||
unsigned int flags = data.flags & ~(NT_NOTIFY_IMMEDIATE | NT_NOTIFY_LOCAL);
|
||||
unsigned int assign_both = NT_NOTIFY_UPDATE | NT_NOTIFY_FLAGS;
|
||||
if ((flags & assign_both) == assign_both) {
|
||||
if ((listen_flags & assign_both) == 0) return false;
|
||||
if ((listen_flags & assign_both) == 0) {
|
||||
return false;
|
||||
}
|
||||
listen_flags &= ~assign_both;
|
||||
flags &= ~assign_both;
|
||||
}
|
||||
if ((flags & ~listen_flags) != 0) return false;
|
||||
if ((flags & ~listen_flags) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// must match local id or prefix
|
||||
if (listener.entry != 0 && data.entry != listener.entry) return false;
|
||||
if (listener.entry == 0 &&
|
||||
!wpi::StringRef(data.name).startswith(listener.prefix))
|
||||
if (listener.entry != 0 && data.entry != listener.entry) {
|
||||
return false;
|
||||
}
|
||||
if (listener.entry == 0 &&
|
||||
!wpi::StringRef(data.name).startswith(listener.prefix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -47,28 +60,36 @@ bool impl::EntryNotifierThread::Matches(const EntryListenerData& listener,
|
||||
unsigned int EntryNotifier::Add(
|
||||
std::function<void(const EntryNotification& event)> callback,
|
||||
StringRef prefix, unsigned int flags) {
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) m_local_notifiers = true;
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) {
|
||||
m_local_notifiers = true;
|
||||
}
|
||||
return DoAdd(callback, prefix, flags);
|
||||
}
|
||||
|
||||
unsigned int EntryNotifier::Add(
|
||||
std::function<void(const EntryNotification& event)> callback,
|
||||
unsigned int local_id, unsigned int flags) {
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) m_local_notifiers = true;
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) {
|
||||
m_local_notifiers = true;
|
||||
}
|
||||
return DoAdd(callback, Handle(m_inst, local_id, Handle::kEntry), flags);
|
||||
}
|
||||
|
||||
unsigned int EntryNotifier::AddPolled(unsigned int poller_uid,
|
||||
wpi::StringRef prefix,
|
||||
unsigned int flags) {
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) m_local_notifiers = true;
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) {
|
||||
m_local_notifiers = true;
|
||||
}
|
||||
return DoAdd(poller_uid, prefix, flags);
|
||||
}
|
||||
|
||||
unsigned int EntryNotifier::AddPolled(unsigned int poller_uid,
|
||||
unsigned int local_id,
|
||||
unsigned int flags) {
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) m_local_notifiers = true;
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0) {
|
||||
m_local_notifiers = true;
|
||||
}
|
||||
return DoAdd(poller_uid, Handle(m_inst, local_id, Handle::kEntry), flags);
|
||||
}
|
||||
|
||||
@@ -78,7 +99,9 @@ void EntryNotifier::NotifyEntry(unsigned int local_id, StringRef name,
|
||||
unsigned int only_listener) {
|
||||
// optimization: don't generate needless local queue entries if we have
|
||||
// no local listeners (as this is a common case on the server side)
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0 && !m_local_notifiers) return;
|
||||
if ((flags & NT_NOTIFY_LOCAL) != 0 && !m_local_notifiers) {
|
||||
return;
|
||||
}
|
||||
DEBUG0("notifying '" << name << "' (local=" << local_id
|
||||
<< "), flags=" << flags);
|
||||
Send(only_listener, 0, Handle(m_inst, local_id, Handle::kEntry).handle(),
|
||||
|
||||
@@ -25,18 +25,26 @@ InstanceImpl::InstanceImpl(int inst)
|
||||
logger.set_min_level(logger_impl.GetMinLevel());
|
||||
}
|
||||
|
||||
InstanceImpl::~InstanceImpl() { logger.SetLogger(nullptr); }
|
||||
InstanceImpl::~InstanceImpl() {
|
||||
logger.SetLogger(nullptr);
|
||||
}
|
||||
|
||||
InstanceImpl* InstanceImpl::GetDefault() { return Get(GetDefaultIndex()); }
|
||||
InstanceImpl* InstanceImpl::GetDefault() {
|
||||
return Get(GetDefaultIndex());
|
||||
}
|
||||
|
||||
InstanceImpl* InstanceImpl::Get(int inst) {
|
||||
if (inst < 0) return nullptr;
|
||||
if (inst < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// fast path, just an atomic read
|
||||
if (static_cast<unsigned int>(inst) <
|
||||
(sizeof(s_fast_instances) / sizeof(s_fast_instances[0]))) {
|
||||
InstanceImpl* ptr = s_fast_instances[inst];
|
||||
if (ptr) return ptr;
|
||||
if (ptr) {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// slow path
|
||||
@@ -60,14 +68,18 @@ InstanceImpl* InstanceImpl::Get(int inst) {
|
||||
|
||||
int InstanceImpl::GetDefaultIndex() {
|
||||
int inst = s_default;
|
||||
if (inst >= 0) return inst;
|
||||
if (inst >= 0) {
|
||||
return inst;
|
||||
}
|
||||
|
||||
// slow path
|
||||
std::scoped_lock lock(s_mutex);
|
||||
|
||||
// double-check
|
||||
inst = s_default;
|
||||
if (inst >= 0) return inst;
|
||||
if (inst >= 0) {
|
||||
return inst;
|
||||
}
|
||||
|
||||
// alloc and save
|
||||
inst = AllocImpl();
|
||||
@@ -94,7 +106,9 @@ int InstanceImpl::AllocImpl() {
|
||||
|
||||
void InstanceImpl::Destroy(int inst) {
|
||||
std::scoped_lock lock(s_mutex);
|
||||
if (inst < 0 || static_cast<unsigned int>(inst) >= s_instances.size()) return;
|
||||
if (inst < 0 || static_cast<unsigned int>(inst) >= s_instances.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (static_cast<unsigned int>(inst) <
|
||||
(sizeof(s_fast_instances) / sizeof(s_fast_instances[0]))) {
|
||||
|
||||
@@ -22,21 +22,24 @@ static void DefaultLogger(unsigned int level, const char* file,
|
||||
}
|
||||
|
||||
wpi::StringRef levelmsg;
|
||||
if (level >= 50)
|
||||
if (level >= 50) {
|
||||
levelmsg = "CRITICAL: ";
|
||||
else if (level >= 40)
|
||||
} else if (level >= 40) {
|
||||
levelmsg = "ERROR: ";
|
||||
else if (level >= 30)
|
||||
} else if (level >= 30) {
|
||||
levelmsg = "WARNING: ";
|
||||
else
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
oss << "NT: " << levelmsg << msg << " (" << file << ':' << line << ")\n";
|
||||
wpi::errs() << oss.str();
|
||||
}
|
||||
|
||||
LoggerImpl::LoggerImpl(int inst) : m_inst(inst) {}
|
||||
|
||||
void LoggerImpl::Start() { DoStart(m_inst); }
|
||||
void LoggerImpl::Start() {
|
||||
DoStart(m_inst);
|
||||
}
|
||||
|
||||
unsigned int LoggerImpl::Add(
|
||||
std::function<void(const LogMessage& msg)> callback, unsigned int min_level,
|
||||
@@ -52,11 +55,15 @@ unsigned int LoggerImpl::AddPolled(unsigned int poller_uid,
|
||||
|
||||
unsigned int LoggerImpl::GetMinLevel() {
|
||||
auto thr = GetThread();
|
||||
if (!thr) return NT_LOG_INFO;
|
||||
if (!thr) {
|
||||
return NT_LOG_INFO;
|
||||
}
|
||||
unsigned int level = NT_LOG_INFO;
|
||||
for (size_t i = 0; i < thr->m_listeners.size(); ++i) {
|
||||
const auto& listener = thr->m_listeners[i];
|
||||
if (listener && listener.min_level < level) level = listener.min_level;
|
||||
if (listener && listener.min_level < level) {
|
||||
level = listener.min_level;
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
@@ -67,8 +74,9 @@ void LoggerImpl::Log(unsigned int level, const char* file, unsigned int line,
|
||||
const char* filename = wpi::sys::path::filename(file).data();
|
||||
{
|
||||
auto thr = GetThread();
|
||||
if (!thr || thr->m_listeners.empty())
|
||||
if (!thr || thr->m_listeners.empty()) {
|
||||
DefaultLogger(level, filename, line, msg);
|
||||
}
|
||||
}
|
||||
Send(UINT_MAX, 0, level, filename, line, msg);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ using namespace nt;
|
||||
std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
GetEntryTypeFunc get_entry_type) {
|
||||
unsigned int msg_type = 0;
|
||||
if (!decoder.Read8(&msg_type)) return nullptr;
|
||||
if (!decoder.Read8(&msg_type)) {
|
||||
return nullptr;
|
||||
}
|
||||
auto msg =
|
||||
std::make_shared<Message>(static_cast<MsgType>(msg_type), private_init());
|
||||
switch (msg_type) {
|
||||
@@ -25,17 +27,23 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
break;
|
||||
case kClientHello: {
|
||||
unsigned int proto_rev;
|
||||
if (!decoder.Read16(&proto_rev)) return nullptr;
|
||||
if (!decoder.Read16(&proto_rev)) {
|
||||
return nullptr;
|
||||
}
|
||||
msg->m_id = proto_rev;
|
||||
// This intentionally uses the provided proto_rev instead of
|
||||
// decoder.proto_rev().
|
||||
if (proto_rev >= 0x0300u) {
|
||||
if (!decoder.ReadString(&msg->m_str)) return nullptr;
|
||||
if (!decoder.ReadString(&msg->m_str)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kProtoUnsup: {
|
||||
if (!decoder.Read16(&msg->m_id)) return nullptr; // proto rev
|
||||
if (!decoder.Read16(&msg->m_id)) {
|
||||
return nullptr; // proto rev
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kServerHelloDone:
|
||||
@@ -45,8 +53,12 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
decoder.set_error("received SERVER_HELLO in protocol < 3.0");
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read8(&msg->m_flags)) return nullptr;
|
||||
if (!decoder.ReadString(&msg->m_str)) return nullptr;
|
||||
if (!decoder.Read8(&msg->m_flags)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.ReadString(&msg->m_str)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case kClientHelloDone:
|
||||
if (decoder.proto_rev() < 0x0300u) {
|
||||
@@ -55,30 +67,50 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
}
|
||||
break;
|
||||
case kEntryAssign: {
|
||||
if (!decoder.ReadString(&msg->m_str)) return nullptr; // name
|
||||
if (!decoder.ReadString(&msg->m_str)) {
|
||||
return nullptr; // name
|
||||
}
|
||||
NT_Type type;
|
||||
if (!decoder.ReadType(&type)) return nullptr; // entry type
|
||||
if (!decoder.Read16(&msg->m_id)) return nullptr; // id
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // seq num
|
||||
if (!decoder.ReadType(&type)) {
|
||||
return nullptr; // entry type
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_id)) {
|
||||
return nullptr; // id
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) {
|
||||
return nullptr; // seq num
|
||||
}
|
||||
if (decoder.proto_rev() >= 0x0300u) {
|
||||
if (!decoder.Read8(&msg->m_flags)) return nullptr; // flags
|
||||
if (!decoder.Read8(&msg->m_flags)) {
|
||||
return nullptr; // flags
|
||||
}
|
||||
}
|
||||
msg->m_value = decoder.ReadValue(type);
|
||||
if (!msg->m_value) return nullptr;
|
||||
if (!msg->m_value) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kEntryUpdate: {
|
||||
if (!decoder.Read16(&msg->m_id)) return nullptr; // id
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // seq num
|
||||
if (!decoder.Read16(&msg->m_id)) {
|
||||
return nullptr; // id
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) {
|
||||
return nullptr; // seq num
|
||||
}
|
||||
NT_Type type;
|
||||
if (decoder.proto_rev() >= 0x0300u) {
|
||||
if (!decoder.ReadType(&type)) return nullptr;
|
||||
if (!decoder.ReadType(&type)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
type = get_entry_type(msg->m_id);
|
||||
}
|
||||
WPI_DEBUG4(decoder.logger(), "update message data type: " << type);
|
||||
msg->m_value = decoder.ReadValue(type);
|
||||
if (!msg->m_value) return nullptr;
|
||||
if (!msg->m_value) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kFlagsUpdate: {
|
||||
@@ -86,8 +118,12 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
decoder.set_error("received FLAGS_UPDATE in protocol < 3.0");
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
||||
if (!decoder.Read8(&msg->m_flags)) return nullptr;
|
||||
if (!decoder.Read16(&msg->m_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read8(&msg->m_flags)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kEntryDelete: {
|
||||
@@ -95,7 +131,9 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
decoder.set_error("received ENTRY_DELETE in protocol < 3.0");
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
||||
if (!decoder.Read16(&msg->m_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kClearEntries: {
|
||||
@@ -104,7 +142,9 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t magic;
|
||||
if (!decoder.Read32(&magic)) return nullptr;
|
||||
if (!decoder.Read32(&magic)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (magic != kClearAllMagic) {
|
||||
decoder.set_error(
|
||||
"received incorrect CLEAR_ENTRIES magic value, ignoring");
|
||||
@@ -117,12 +157,20 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
decoder.set_error("received EXECUTE_RPC in protocol < 3.0");
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // uid
|
||||
if (!decoder.Read16(&msg->m_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) {
|
||||
return nullptr; // uid
|
||||
}
|
||||
uint64_t size;
|
||||
if (!decoder.ReadUleb128(&size)) return nullptr;
|
||||
if (!decoder.ReadUleb128(&size)) {
|
||||
return nullptr;
|
||||
}
|
||||
const char* params;
|
||||
if (!decoder.Read(¶ms, size)) return nullptr;
|
||||
if (!decoder.Read(¶ms, size)) {
|
||||
return nullptr;
|
||||
}
|
||||
msg->m_str = wpi::StringRef(params, size);
|
||||
break;
|
||||
}
|
||||
@@ -131,12 +179,20 @@ std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
||||
decoder.set_error("received RPC_RESPONSE in protocol < 3.0");
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // uid
|
||||
if (!decoder.Read16(&msg->m_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!decoder.Read16(&msg->m_seq_num_uid)) {
|
||||
return nullptr; // uid
|
||||
}
|
||||
uint64_t size;
|
||||
if (!decoder.ReadUleb128(&size)) return nullptr;
|
||||
if (!decoder.ReadUleb128(&size)) {
|
||||
return nullptr;
|
||||
}
|
||||
const char* results;
|
||||
if (!decoder.Read(&results, size)) return nullptr;
|
||||
if (!decoder.Read(&results, size)) {
|
||||
return nullptr;
|
||||
}
|
||||
msg->m_str = wpi::StringRef(results, size);
|
||||
break;
|
||||
}
|
||||
@@ -226,7 +282,9 @@ void Message::Write(WireEncoder& encoder) const {
|
||||
case kClientHello:
|
||||
encoder.Write8(kClientHello);
|
||||
encoder.Write16(encoder.proto_rev());
|
||||
if (encoder.proto_rev() < 0x0300u) return;
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return;
|
||||
}
|
||||
encoder.WriteString(m_str);
|
||||
break;
|
||||
case kProtoUnsup:
|
||||
@@ -237,13 +295,17 @@ void Message::Write(WireEncoder& encoder) const {
|
||||
encoder.Write8(kServerHelloDone);
|
||||
break;
|
||||
case kServerHello:
|
||||
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return; // new message in version 3.0
|
||||
}
|
||||
encoder.Write8(kServerHello);
|
||||
encoder.Write8(m_flags);
|
||||
encoder.WriteString(m_str);
|
||||
break;
|
||||
case kClientHelloDone:
|
||||
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return; // new message in version 3.0
|
||||
}
|
||||
encoder.Write8(kClientHelloDone);
|
||||
break;
|
||||
case kEntryAssign:
|
||||
@@ -252,41 +314,55 @@ void Message::Write(WireEncoder& encoder) const {
|
||||
encoder.WriteType(m_value->type());
|
||||
encoder.Write16(m_id);
|
||||
encoder.Write16(m_seq_num_uid);
|
||||
if (encoder.proto_rev() >= 0x0300u) encoder.Write8(m_flags);
|
||||
if (encoder.proto_rev() >= 0x0300u) {
|
||||
encoder.Write8(m_flags);
|
||||
}
|
||||
encoder.WriteValue(*m_value);
|
||||
break;
|
||||
case kEntryUpdate:
|
||||
encoder.Write8(kEntryUpdate);
|
||||
encoder.Write16(m_id);
|
||||
encoder.Write16(m_seq_num_uid);
|
||||
if (encoder.proto_rev() >= 0x0300u) encoder.WriteType(m_value->type());
|
||||
if (encoder.proto_rev() >= 0x0300u) {
|
||||
encoder.WriteType(m_value->type());
|
||||
}
|
||||
encoder.WriteValue(*m_value);
|
||||
break;
|
||||
case kFlagsUpdate:
|
||||
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return; // new message in version 3.0
|
||||
}
|
||||
encoder.Write8(kFlagsUpdate);
|
||||
encoder.Write16(m_id);
|
||||
encoder.Write8(m_flags);
|
||||
break;
|
||||
case kEntryDelete:
|
||||
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return; // new message in version 3.0
|
||||
}
|
||||
encoder.Write8(kEntryDelete);
|
||||
encoder.Write16(m_id);
|
||||
break;
|
||||
case kClearEntries:
|
||||
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return; // new message in version 3.0
|
||||
}
|
||||
encoder.Write8(kClearEntries);
|
||||
encoder.Write32(kClearAllMagic);
|
||||
break;
|
||||
case kExecuteRpc:
|
||||
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return; // new message in version 3.0
|
||||
}
|
||||
encoder.Write8(kExecuteRpc);
|
||||
encoder.Write16(m_id);
|
||||
encoder.Write16(m_seq_num_uid);
|
||||
encoder.WriteString(m_str);
|
||||
break;
|
||||
case kRpcResponse:
|
||||
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
|
||||
if (encoder.proto_rev() < 0x0300u) {
|
||||
return; // new message in version 3.0
|
||||
}
|
||||
encoder.Write8(kRpcResponse);
|
||||
encoder.Write16(m_id);
|
||||
encoder.Write16(m_seq_num_uid);
|
||||
|
||||
@@ -36,14 +36,20 @@ NetworkConnection::NetworkConnection(unsigned int uid,
|
||||
m_stream->setNoDelay();
|
||||
}
|
||||
|
||||
NetworkConnection::~NetworkConnection() { Stop(); }
|
||||
NetworkConnection::~NetworkConnection() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void NetworkConnection::Start() {
|
||||
if (m_active) return;
|
||||
if (m_active) {
|
||||
return;
|
||||
}
|
||||
m_active = true;
|
||||
set_state(kInit);
|
||||
// clear queue
|
||||
while (!m_outgoing.empty()) m_outgoing.pop();
|
||||
while (!m_outgoing.empty()) {
|
||||
m_outgoing.pop();
|
||||
}
|
||||
// reset shutdown flags
|
||||
{
|
||||
std::scoped_lock lock(m_shutdown_mutex);
|
||||
@@ -60,7 +66,9 @@ void NetworkConnection::Stop() {
|
||||
set_state(kDead);
|
||||
m_active = false;
|
||||
// closing the stream so the read thread terminates
|
||||
if (m_stream) m_stream->close();
|
||||
if (m_stream) {
|
||||
m_stream->close();
|
||||
}
|
||||
// send an empty outgoing message set so the write thread terminates
|
||||
m_outgoing.push(Outgoing());
|
||||
// wait for threads to terminate, with timeout
|
||||
@@ -69,23 +77,27 @@ void NetworkConnection::Stop() {
|
||||
auto timeout_time =
|
||||
std::chrono::steady_clock::now() + std::chrono::milliseconds(200);
|
||||
if (m_write_shutdown_cv.wait_until(lock, timeout_time,
|
||||
[&] { return m_write_shutdown; }))
|
||||
[&] { return m_write_shutdown; })) {
|
||||
m_write_thread.join();
|
||||
else
|
||||
} else {
|
||||
m_write_thread.detach(); // timed out, detach it
|
||||
}
|
||||
}
|
||||
if (m_read_thread.joinable()) {
|
||||
std::unique_lock lock(m_shutdown_mutex);
|
||||
auto timeout_time =
|
||||
std::chrono::steady_clock::now() + std::chrono::milliseconds(200);
|
||||
if (m_read_shutdown_cv.wait_until(lock, timeout_time,
|
||||
[&] { return m_read_shutdown; }))
|
||||
[&] { return m_read_shutdown; })) {
|
||||
m_read_thread.join();
|
||||
else
|
||||
} else {
|
||||
m_read_thread.detach(); // timed out, detach it
|
||||
}
|
||||
}
|
||||
// clear queue
|
||||
while (!m_outgoing.empty()) m_outgoing.pop();
|
||||
while (!m_outgoing.empty()) {
|
||||
m_outgoing.pop();
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionInfo NetworkConnection::info() const {
|
||||
@@ -94,7 +106,9 @@ ConnectionInfo NetworkConnection::info() const {
|
||||
m_last_update, m_proto_rev};
|
||||
}
|
||||
|
||||
unsigned int NetworkConnection::proto_rev() const { return m_proto_rev; }
|
||||
unsigned int NetworkConnection::proto_rev() const {
|
||||
return m_proto_rev;
|
||||
}
|
||||
|
||||
void NetworkConnection::set_proto_rev(unsigned int proto_rev) {
|
||||
m_proto_rev = proto_rev;
|
||||
@@ -108,12 +122,16 @@ NetworkConnection::State NetworkConnection::state() const {
|
||||
void NetworkConnection::set_state(State state) {
|
||||
std::scoped_lock lock(m_state_mutex);
|
||||
// Don't update state any more once we've died
|
||||
if (m_state == kDead) return;
|
||||
if (m_state == kDead) {
|
||||
return;
|
||||
}
|
||||
// One-shot notify state changes
|
||||
if (m_state != kActive && state == kActive)
|
||||
if (m_state != kActive && state == kActive) {
|
||||
m_notifier.NotifyConnection(true, info());
|
||||
if (m_state != kDead && state == kDead)
|
||||
}
|
||||
if (m_state != kDead && state == kDead) {
|
||||
m_notifier.NotifyConnection(false, info());
|
||||
}
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
@@ -137,8 +155,9 @@ void NetworkConnection::ReadThreadMain() {
|
||||
[&] {
|
||||
decoder.set_proto_rev(m_proto_rev);
|
||||
auto msg = Message::Read(decoder, m_get_entry_type);
|
||||
if (!msg && decoder.error())
|
||||
if (!msg && decoder.error()) {
|
||||
DEBUG0("error reading in handshake: " << decoder.error());
|
||||
}
|
||||
return msg;
|
||||
},
|
||||
[&](wpi::ArrayRef<std::shared_ptr<Message>> msgs) {
|
||||
@@ -151,14 +170,20 @@ void NetworkConnection::ReadThreadMain() {
|
||||
|
||||
set_state(kActive);
|
||||
while (m_active) {
|
||||
if (!m_stream) break;
|
||||
if (!m_stream) {
|
||||
break;
|
||||
}
|
||||
decoder.set_proto_rev(m_proto_rev);
|
||||
decoder.Reset();
|
||||
auto msg = Message::Read(decoder, m_get_entry_type);
|
||||
if (!msg) {
|
||||
if (decoder.error()) INFO("read error: " << decoder.error());
|
||||
if (decoder.error()) {
|
||||
INFO("read error: " << decoder.error());
|
||||
}
|
||||
// terminate connection on bad message
|
||||
if (m_stream) m_stream->close();
|
||||
if (m_stream) {
|
||||
m_stream->close();
|
||||
}
|
||||
break;
|
||||
}
|
||||
DEBUG3("received type=" << msg->type() << " with str=" << msg->str()
|
||||
@@ -187,7 +212,9 @@ void NetworkConnection::WriteThreadMain() {
|
||||
while (m_active) {
|
||||
auto msgs = m_outgoing.pop();
|
||||
DEBUG4("write thread woke up");
|
||||
if (msgs.empty()) continue;
|
||||
if (msgs.empty()) {
|
||||
continue;
|
||||
}
|
||||
encoder.set_proto_rev(m_proto_rev);
|
||||
encoder.Reset();
|
||||
DEBUG3("sending " << msgs.size() << " messages");
|
||||
@@ -200,15 +227,23 @@ void NetworkConnection::WriteThreadMain() {
|
||||
}
|
||||
}
|
||||
wpi::NetworkStream::Error err;
|
||||
if (!m_stream) break;
|
||||
if (encoder.size() == 0) continue;
|
||||
if (m_stream->send(encoder.data(), encoder.size(), &err) == 0) break;
|
||||
if (!m_stream) {
|
||||
break;
|
||||
}
|
||||
if (encoder.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
if (m_stream->send(encoder.data(), encoder.size(), &err) == 0) {
|
||||
break;
|
||||
}
|
||||
DEBUG4("sent " << encoder.size() << " bytes");
|
||||
}
|
||||
DEBUG2("write thread died (" << this << ")");
|
||||
set_state(kDead);
|
||||
m_active = false;
|
||||
if (m_stream) m_stream->close(); // also kill read thread
|
||||
if (m_stream) {
|
||||
m_stream->close(); // also kill read thread
|
||||
}
|
||||
|
||||
// use condition variable to signal thread shutdown
|
||||
{
|
||||
@@ -246,7 +281,9 @@ void NetworkConnection::QueueOutgoing(std::shared_ptr<Message> msg) {
|
||||
// new, but remember it
|
||||
size_t pos = m_pending_outgoing.size();
|
||||
m_pending_outgoing.push_back(msg);
|
||||
if (id >= m_pending_update.size()) m_pending_update.resize(id + 1);
|
||||
if (id >= m_pending_update.size()) {
|
||||
m_pending_update.resize(id + 1);
|
||||
}
|
||||
m_pending_update[id].first = pos + 1;
|
||||
}
|
||||
break;
|
||||
@@ -289,7 +326,9 @@ void NetworkConnection::QueueOutgoing(std::shared_ptr<Message> msg) {
|
||||
// new, but remember it
|
||||
size_t pos = m_pending_outgoing.size();
|
||||
m_pending_outgoing.push_back(msg);
|
||||
if (id >= m_pending_update.size()) m_pending_update.resize(id + 1);
|
||||
if (id >= m_pending_update.size()) {
|
||||
m_pending_update.resize(id + 1);
|
||||
}
|
||||
m_pending_update[id].second = pos + 1;
|
||||
}
|
||||
break;
|
||||
@@ -297,12 +336,15 @@ void NetworkConnection::QueueOutgoing(std::shared_ptr<Message> msg) {
|
||||
case Message::kClearEntries: {
|
||||
// knock out all previous assigns/updates!
|
||||
for (auto& i : m_pending_outgoing) {
|
||||
if (!i) continue;
|
||||
if (!i) {
|
||||
continue;
|
||||
}
|
||||
auto t = i->type();
|
||||
if (t == Message::kEntryAssign || t == Message::kEntryUpdate ||
|
||||
t == Message::kFlagsUpdate || t == Message::kEntryDelete ||
|
||||
t == Message::kClearEntries)
|
||||
t == Message::kClearEntries) {
|
||||
i.reset();
|
||||
}
|
||||
}
|
||||
m_pending_update.resize(0);
|
||||
m_pending_outgoing.push_back(msg);
|
||||
@@ -318,9 +360,13 @@ void NetworkConnection::PostOutgoing(bool keep_alive) {
|
||||
std::scoped_lock lock(m_pending_mutex);
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (m_pending_outgoing.empty()) {
|
||||
if (!keep_alive) return;
|
||||
if (!keep_alive) {
|
||||
return;
|
||||
}
|
||||
// send keep-alives once a second (if no other messages have been sent)
|
||||
if ((now - m_last_post) < std::chrono::seconds(1)) return;
|
||||
if ((now - m_last_post) < std::chrono::seconds(1)) {
|
||||
return;
|
||||
}
|
||||
m_outgoing.emplace(Outgoing{Message::KeepAlive()});
|
||||
} else {
|
||||
m_outgoing.emplace(std::move(m_pending_outgoing));
|
||||
|
||||
@@ -9,7 +9,9 @@ using namespace nt;
|
||||
RpcServer::RpcServer(int inst, wpi::Logger& logger)
|
||||
: m_inst(inst), m_logger(logger) {}
|
||||
|
||||
void RpcServer::Start() { DoStart(m_inst, m_logger); }
|
||||
void RpcServer::Start() {
|
||||
DoStart(m_inst, m_logger);
|
||||
}
|
||||
|
||||
unsigned int RpcServer::Add(
|
||||
std::function<void(const RpcAnswer& answer)> callback) {
|
||||
@@ -20,7 +22,9 @@ unsigned int RpcServer::AddPolled(unsigned int poller_uid) {
|
||||
return DoAdd(poller_uid);
|
||||
}
|
||||
|
||||
void RpcServer::RemoveRpc(unsigned int rpc_uid) { Remove(rpc_uid); }
|
||||
void RpcServer::RemoveRpc(unsigned int rpc_uid) {
|
||||
Remove(rpc_uid);
|
||||
}
|
||||
|
||||
void RpcServer::ProcessRpc(unsigned int local_id, unsigned int call_uid,
|
||||
StringRef name, StringRef params,
|
||||
|
||||
@@ -7,21 +7,23 @@
|
||||
namespace nt {
|
||||
|
||||
bool operator<(const SequenceNumber& lhs, const SequenceNumber& rhs) {
|
||||
if (lhs.m_value < rhs.m_value)
|
||||
if (lhs.m_value < rhs.m_value) {
|
||||
return (rhs.m_value - lhs.m_value) < (1u << 15);
|
||||
else if (lhs.m_value > rhs.m_value)
|
||||
} else if (lhs.m_value > rhs.m_value) {
|
||||
return (lhs.m_value - rhs.m_value) > (1u << 15);
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator>(const SequenceNumber& lhs, const SequenceNumber& rhs) {
|
||||
if (lhs.m_value < rhs.m_value)
|
||||
if (lhs.m_value < rhs.m_value) {
|
||||
return (rhs.m_value - lhs.m_value) > (1u << 15);
|
||||
else if (lhs.m_value > rhs.m_value)
|
||||
} else if (lhs.m_value > rhs.m_value) {
|
||||
return (lhs.m_value - rhs.m_value) < (1u << 15);
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nt
|
||||
|
||||
@@ -16,7 +16,9 @@ class SequenceNumber {
|
||||
|
||||
SequenceNumber& operator++() {
|
||||
++m_value;
|
||||
if (m_value > 0xffff) m_value = 0;
|
||||
if (m_value > 0xffff) {
|
||||
m_value = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
SequenceNumber operator++(int) {
|
||||
|
||||
@@ -32,13 +32,19 @@ void Storage::SetDispatcher(IDispatcher* dispatcher, bool server) {
|
||||
m_server = server;
|
||||
}
|
||||
|
||||
void Storage::ClearDispatcher() { m_dispatcher = nullptr; }
|
||||
void Storage::ClearDispatcher() {
|
||||
m_dispatcher = nullptr;
|
||||
}
|
||||
|
||||
NT_Type Storage::GetMessageEntryType(unsigned int id) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (id >= m_idmap.size()) return NT_UNASSIGNED;
|
||||
if (id >= m_idmap.size()) {
|
||||
return NT_UNASSIGNED;
|
||||
}
|
||||
Entry* entry = m_idmap[id];
|
||||
if (!entry || !entry->value) return NT_UNASSIGNED;
|
||||
if (!entry || !entry->value) {
|
||||
return NT_UNASSIGNED;
|
||||
}
|
||||
return entry->value->type();
|
||||
}
|
||||
|
||||
@@ -96,7 +102,9 @@ void Storage::ProcessIncomingEntryAssign(std::shared_ptr<Message> msg,
|
||||
if (id == 0xffff) {
|
||||
entry = GetOrNew(name);
|
||||
// see if it was already assigned; ignore if so.
|
||||
if (entry->id != 0xffff) return;
|
||||
if (entry->id != 0xffff) {
|
||||
return;
|
||||
}
|
||||
|
||||
entry->flags = msg->flags();
|
||||
entry->seq_num = seq_num;
|
||||
@@ -118,7 +126,9 @@ void Storage::ProcessIncomingEntryAssign(std::shared_ptr<Message> msg,
|
||||
DEBUG0("client: received entry assignment request?");
|
||||
return;
|
||||
}
|
||||
if (id >= m_idmap.size()) m_idmap.resize(id + 1);
|
||||
if (id >= m_idmap.size()) {
|
||||
m_idmap.resize(id + 1);
|
||||
}
|
||||
entry = m_idmap[id];
|
||||
if (!entry) {
|
||||
// create local
|
||||
@@ -178,15 +188,19 @@ void Storage::ProcessIncomingEntryAssign(std::shared_ptr<Message> msg,
|
||||
// don't update flags if this is a server response to a client id request
|
||||
if (!may_need_update && conn->proto_rev() >= 0x0300) {
|
||||
// update persistent dirty flag if persistent flag changed
|
||||
if ((entry->flags & NT_PERSISTENT) != (msg->flags() & NT_PERSISTENT))
|
||||
if ((entry->flags & NT_PERSISTENT) != (msg->flags() & NT_PERSISTENT)) {
|
||||
m_persistent_dirty = true;
|
||||
if (entry->flags != msg->flags()) notify_flags |= NT_NOTIFY_FLAGS;
|
||||
}
|
||||
if (entry->flags != msg->flags()) {
|
||||
notify_flags |= NT_NOTIFY_FLAGS;
|
||||
}
|
||||
entry->flags = msg->flags();
|
||||
}
|
||||
|
||||
// update persistent dirty flag if the value changed and it's persistent
|
||||
if (entry->IsPersistent() && *entry->value != *msg->value())
|
||||
if (entry->IsPersistent() && *entry->value != *msg->value()) {
|
||||
m_persistent_dirty = true;
|
||||
}
|
||||
|
||||
// update local
|
||||
entry->value = msg->value();
|
||||
@@ -221,14 +235,18 @@ void Storage::ProcessIncomingEntryUpdate(std::shared_ptr<Message> msg,
|
||||
|
||||
// ignore if sequence number not higher than local
|
||||
SequenceNumber seq_num(msg->seq_num_uid());
|
||||
if (seq_num <= entry->seq_num) return;
|
||||
if (seq_num <= entry->seq_num) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update local
|
||||
entry->value = msg->value();
|
||||
entry->seq_num = seq_num;
|
||||
|
||||
// update persistent dirty flag if it's a persistent value
|
||||
if (entry->IsPersistent()) m_persistent_dirty = true;
|
||||
if (entry->IsPersistent()) {
|
||||
m_persistent_dirty = true;
|
||||
}
|
||||
|
||||
// notify
|
||||
m_notifier.NotifyEntry(entry->local_id, entry->name, entry->value,
|
||||
@@ -310,7 +328,9 @@ void Storage::ProcessIncomingExecuteRpc(
|
||||
std::shared_ptr<Message> msg, INetworkConnection* /*conn*/,
|
||||
std::weak_ptr<INetworkConnection> conn_weak) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (!m_server) return; // only process on server
|
||||
if (!m_server) {
|
||||
return; // only process on server
|
||||
}
|
||||
unsigned int id = msg->id();
|
||||
if (id >= m_idmap.size() || !m_idmap[id]) {
|
||||
// ignore call to non-existent RPC
|
||||
@@ -341,7 +361,9 @@ void Storage::ProcessIncomingExecuteRpc(
|
||||
entry->local_id, call_uid, entry->name, msg->str(), conn_info,
|
||||
[=](StringRef result) {
|
||||
auto c = conn_weak.lock();
|
||||
if (c) c->QueueOutgoing(Message::RpcResponse(id, call_uid, result));
|
||||
if (c) {
|
||||
c->QueueOutgoing(Message::RpcResponse(id, call_uid, result));
|
||||
}
|
||||
},
|
||||
entry->rpc_uid);
|
||||
}
|
||||
@@ -349,7 +371,9 @@ void Storage::ProcessIncomingExecuteRpc(
|
||||
void Storage::ProcessIncomingRpcResponse(std::shared_ptr<Message> msg,
|
||||
INetworkConnection* /*conn*/) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (m_server) return; // only process on client
|
||||
if (m_server) {
|
||||
return; // only process on client
|
||||
}
|
||||
unsigned int id = msg->id();
|
||||
if (id >= m_idmap.size() || !m_idmap[id]) {
|
||||
// ignore response to non-existent RPC
|
||||
@@ -375,7 +399,9 @@ void Storage::GetInitialAssignments(
|
||||
conn.set_state(INetworkConnection::kSynchronized);
|
||||
for (auto& i : m_entries) {
|
||||
Entry* entry = i.getValue();
|
||||
if (!entry->value) continue;
|
||||
if (!entry->value) {
|
||||
continue;
|
||||
}
|
||||
msgs->emplace_back(Message::EntryAssign(i.getKey(), entry->id,
|
||||
entry->seq_num.value(),
|
||||
entry->value, entry->flags));
|
||||
@@ -386,14 +412,18 @@ void Storage::ApplyInitialAssignments(
|
||||
INetworkConnection& conn, wpi::ArrayRef<std::shared_ptr<Message>> msgs,
|
||||
bool /*new_server*/, std::vector<std::shared_ptr<Message>>* out_msgs) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (m_server) return; // should not do this on server
|
||||
if (m_server) {
|
||||
return; // should not do this on server
|
||||
}
|
||||
|
||||
conn.set_state(INetworkConnection::kSynchronized);
|
||||
|
||||
std::vector<std::shared_ptr<Message>> update_msgs;
|
||||
|
||||
// clear existing id's
|
||||
for (auto& i : m_entries) i.getValue()->id = 0xffff;
|
||||
for (auto& i : m_entries) {
|
||||
i.getValue()->id = 0xffff;
|
||||
}
|
||||
|
||||
// clear existing idmap
|
||||
m_idmap.resize(0);
|
||||
@@ -437,7 +467,9 @@ void Storage::ApplyInitialAssignments(
|
||||
unsigned int notify_flags = NT_NOTIFY_UPDATE;
|
||||
// don't update flags from a <3.0 remote (not part of message)
|
||||
if (conn.proto_rev() >= 0x0300) {
|
||||
if (entry->flags != msg->flags()) notify_flags |= NT_NOTIFY_FLAGS;
|
||||
if (entry->flags != msg->flags()) {
|
||||
notify_flags |= NT_NOTIFY_FLAGS;
|
||||
}
|
||||
entry->flags = msg->flags();
|
||||
}
|
||||
// notify
|
||||
@@ -447,14 +479,18 @@ void Storage::ApplyInitialAssignments(
|
||||
}
|
||||
|
||||
// save to idmap
|
||||
if (id >= m_idmap.size()) m_idmap.resize(id + 1);
|
||||
if (id >= m_idmap.size()) {
|
||||
m_idmap.resize(id + 1);
|
||||
}
|
||||
m_idmap[id] = entry;
|
||||
}
|
||||
|
||||
// delete or generate assign messages for unassigned local entries
|
||||
DeleteAllEntriesImpl(false, [&](Entry* entry) -> bool {
|
||||
// was assigned by the server, don't delete
|
||||
if (entry->id != 0xffff) return false;
|
||||
if (entry->id != 0xffff) {
|
||||
return false;
|
||||
}
|
||||
// if we have written the value locally, we send an assign message to the
|
||||
// server instead of deleting
|
||||
if (entry->local_write) {
|
||||
@@ -468,32 +504,43 @@ void Storage::ApplyInitialAssignments(
|
||||
});
|
||||
auto dispatcher = m_dispatcher;
|
||||
lock.unlock();
|
||||
for (auto& msg : update_msgs)
|
||||
for (auto& msg : update_msgs) {
|
||||
dispatcher->QueueOutgoing(msg, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Value> Storage::GetEntryValue(StringRef name) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto i = m_entries.find(name);
|
||||
if (i == m_entries.end()) return nullptr;
|
||||
if (i == m_entries.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return i->getValue()->value;
|
||||
}
|
||||
|
||||
std::shared_ptr<Value> Storage::GetEntryValue(unsigned int local_id) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return nullptr;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_localmap[local_id]->value;
|
||||
}
|
||||
|
||||
bool Storage::SetDefaultEntryValue(StringRef name,
|
||||
std::shared_ptr<Value> value) {
|
||||
if (name.empty()) return false;
|
||||
if (!value) return false;
|
||||
if (name.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
Entry* entry = GetOrNew(name);
|
||||
|
||||
// we return early if value already exists; if types match return true
|
||||
if (entry->value) return entry->value->type() == value->type();
|
||||
if (entry->value) {
|
||||
return entry->value->type() == value->type();
|
||||
}
|
||||
|
||||
SetEntryValueImpl(entry, value, lock, true);
|
||||
return true;
|
||||
@@ -501,26 +548,37 @@ bool Storage::SetDefaultEntryValue(StringRef name,
|
||||
|
||||
bool Storage::SetDefaultEntryValue(unsigned int local_id,
|
||||
std::shared_ptr<Value> value) {
|
||||
if (!value) return false;
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return false;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return false;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
|
||||
// we return early if value already exists; if types match return true
|
||||
if (entry->value) return entry->value->type() == value->type();
|
||||
if (entry->value) {
|
||||
return entry->value->type() == value->type();
|
||||
}
|
||||
|
||||
SetEntryValueImpl(entry, value, lock, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Storage::SetEntryValue(StringRef name, std::shared_ptr<Value> value) {
|
||||
if (name.empty()) return true;
|
||||
if (!value) return true;
|
||||
if (name.empty()) {
|
||||
return true;
|
||||
}
|
||||
if (!value) {
|
||||
return true;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
Entry* entry = GetOrNew(name);
|
||||
|
||||
if (entry->value && entry->value->type() != value->type())
|
||||
if (entry->value && entry->value->type() != value->type()) {
|
||||
return false; // error on type mismatch
|
||||
}
|
||||
|
||||
SetEntryValueImpl(entry, value, lock, true);
|
||||
return true;
|
||||
@@ -528,13 +586,18 @@ bool Storage::SetEntryValue(StringRef name, std::shared_ptr<Value> value) {
|
||||
|
||||
bool Storage::SetEntryValue(unsigned int local_id,
|
||||
std::shared_ptr<Value> value) {
|
||||
if (!value) return true;
|
||||
if (!value) {
|
||||
return true;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return true;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return true;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
|
||||
if (entry->value && entry->value->type() != value->type())
|
||||
if (entry->value && entry->value->type() != value->type()) {
|
||||
return false; // error on type mismatch
|
||||
}
|
||||
|
||||
SetEntryValueImpl(entry, value, lock, true);
|
||||
return true;
|
||||
@@ -543,7 +606,9 @@ bool Storage::SetEntryValue(unsigned int local_id,
|
||||
void Storage::SetEntryValueImpl(Entry* entry, std::shared_ptr<Value> value,
|
||||
std::unique_lock<wpi::mutex>& lock,
|
||||
bool local) {
|
||||
if (!value) return;
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
auto old_value = entry->value;
|
||||
entry->value = value;
|
||||
|
||||
@@ -555,31 +620,41 @@ void Storage::SetEntryValueImpl(Entry* entry, std::shared_ptr<Value> value,
|
||||
}
|
||||
|
||||
// update persistent dirty flag if value changed and it's persistent
|
||||
if (entry->IsPersistent() && (!old_value || *old_value != *value))
|
||||
if (entry->IsPersistent() && (!old_value || *old_value != *value)) {
|
||||
m_persistent_dirty = true;
|
||||
}
|
||||
|
||||
// notify
|
||||
if (!old_value)
|
||||
if (!old_value) {
|
||||
m_notifier.NotifyEntry(entry->local_id, entry->name, value,
|
||||
NT_NOTIFY_NEW | (local ? NT_NOTIFY_LOCAL : 0));
|
||||
else if (*old_value != *value)
|
||||
} else if (*old_value != *value) {
|
||||
m_notifier.NotifyEntry(entry->local_id, entry->name, value,
|
||||
NT_NOTIFY_UPDATE | (local ? NT_NOTIFY_LOCAL : 0));
|
||||
}
|
||||
|
||||
// remember local changes
|
||||
if (local) entry->local_write = true;
|
||||
if (local) {
|
||||
entry->local_write = true;
|
||||
}
|
||||
|
||||
// generate message
|
||||
if (!m_dispatcher || (!local && !m_server)) return;
|
||||
if (!m_dispatcher || (!local && !m_server)) {
|
||||
return;
|
||||
}
|
||||
auto dispatcher = m_dispatcher;
|
||||
if (!old_value || old_value->type() != value->type()) {
|
||||
if (local) ++entry->seq_num;
|
||||
if (local) {
|
||||
++entry->seq_num;
|
||||
}
|
||||
auto msg = Message::EntryAssign(
|
||||
entry->name, entry->id, entry->seq_num.value(), value, entry->flags);
|
||||
lock.unlock();
|
||||
dispatcher->QueueOutgoing(msg, nullptr, nullptr);
|
||||
} else if (*old_value != *value) {
|
||||
if (local) ++entry->seq_num;
|
||||
if (local) {
|
||||
++entry->seq_num;
|
||||
}
|
||||
// don't send an update if we don't have an assigned id yet
|
||||
if (entry->id != 0xffff) {
|
||||
auto msg = Message::EntryUpdate(entry->id, entry->seq_num.value(), value);
|
||||
@@ -590,8 +665,12 @@ void Storage::SetEntryValueImpl(Entry* entry, std::shared_ptr<Value> value,
|
||||
}
|
||||
|
||||
void Storage::SetEntryTypeValue(StringRef name, std::shared_ptr<Value> value) {
|
||||
if (name.empty()) return;
|
||||
if (!value) return;
|
||||
if (name.empty()) {
|
||||
return;
|
||||
}
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
Entry* entry = GetOrNew(name);
|
||||
|
||||
@@ -600,37 +679,52 @@ void Storage::SetEntryTypeValue(StringRef name, std::shared_ptr<Value> value) {
|
||||
|
||||
void Storage::SetEntryTypeValue(unsigned int local_id,
|
||||
std::shared_ptr<Value> value) {
|
||||
if (!value) return;
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
if (!entry) return;
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetEntryValueImpl(entry, value, lock, true);
|
||||
}
|
||||
|
||||
void Storage::SetEntryFlags(StringRef name, unsigned int flags) {
|
||||
if (name.empty()) return;
|
||||
if (name.empty()) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
auto i = m_entries.find(name);
|
||||
if (i == m_entries.end()) return;
|
||||
if (i == m_entries.end()) {
|
||||
return;
|
||||
}
|
||||
SetEntryFlagsImpl(i->getValue(), flags, lock, true);
|
||||
}
|
||||
|
||||
void Storage::SetEntryFlags(unsigned int id_local, unsigned int flags) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (id_local >= m_localmap.size()) return;
|
||||
if (id_local >= m_localmap.size()) {
|
||||
return;
|
||||
}
|
||||
SetEntryFlagsImpl(m_localmap[id_local].get(), flags, lock, true);
|
||||
}
|
||||
|
||||
void Storage::SetEntryFlagsImpl(Entry* entry, unsigned int flags,
|
||||
std::unique_lock<wpi::mutex>& lock,
|
||||
bool local) {
|
||||
if (!entry->value || entry->flags == flags) return;
|
||||
if (!entry->value || entry->flags == flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update persistent dirty flag if persistent flag changed
|
||||
if ((entry->flags & NT_PERSISTENT) != (flags & NT_PERSISTENT))
|
||||
if ((entry->flags & NT_PERSISTENT) != (flags & NT_PERSISTENT)) {
|
||||
m_persistent_dirty = true;
|
||||
}
|
||||
|
||||
entry->flags = flags;
|
||||
|
||||
@@ -639,7 +733,9 @@ void Storage::SetEntryFlagsImpl(Entry* entry, unsigned int flags,
|
||||
NT_NOTIFY_FLAGS | (local ? NT_NOTIFY_LOCAL : 0));
|
||||
|
||||
// generate message
|
||||
if (!local || !m_dispatcher) return;
|
||||
if (!local || !m_dispatcher) {
|
||||
return;
|
||||
}
|
||||
auto dispatcher = m_dispatcher;
|
||||
unsigned int id = entry->id;
|
||||
// don't send an update if we don't have an assigned id yet
|
||||
@@ -653,26 +749,34 @@ void Storage::SetEntryFlagsImpl(Entry* entry, unsigned int flags,
|
||||
unsigned int Storage::GetEntryFlags(StringRef name) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto i = m_entries.find(name);
|
||||
if (i == m_entries.end()) return 0;
|
||||
if (i == m_entries.end()) {
|
||||
return 0;
|
||||
}
|
||||
return i->getValue()->flags;
|
||||
}
|
||||
|
||||
unsigned int Storage::GetEntryFlags(unsigned int local_id) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return 0;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return 0;
|
||||
}
|
||||
return m_localmap[local_id]->flags;
|
||||
}
|
||||
|
||||
void Storage::DeleteEntry(StringRef name) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
auto i = m_entries.find(name);
|
||||
if (i == m_entries.end()) return;
|
||||
if (i == m_entries.end()) {
|
||||
return;
|
||||
}
|
||||
DeleteEntryImpl(i->getValue(), lock, true);
|
||||
}
|
||||
|
||||
void Storage::DeleteEntry(unsigned int local_id) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return;
|
||||
}
|
||||
DeleteEntryImpl(m_localmap[local_id].get(), lock, true);
|
||||
}
|
||||
|
||||
@@ -681,7 +785,9 @@ void Storage::DeleteEntryImpl(Entry* entry, std::unique_lock<wpi::mutex>& lock,
|
||||
unsigned int id = entry->id;
|
||||
|
||||
// Erase entry from id mapping.
|
||||
if (id < m_idmap.size()) m_idmap[id] = nullptr;
|
||||
if (id < m_idmap.size()) {
|
||||
m_idmap[id] = nullptr;
|
||||
}
|
||||
|
||||
// empty the value and reset id and local_write flag
|
||||
std::shared_ptr<Value> old_value;
|
||||
@@ -696,12 +802,16 @@ void Storage::DeleteEntryImpl(Entry* entry, std::unique_lock<wpi::mutex>& lock,
|
||||
}
|
||||
|
||||
// update persistent dirty flag if it's a persistent value
|
||||
if (entry->IsPersistent()) m_persistent_dirty = true;
|
||||
if (entry->IsPersistent()) {
|
||||
m_persistent_dirty = true;
|
||||
}
|
||||
|
||||
// reset flags
|
||||
entry->flags = 0;
|
||||
|
||||
if (!old_value) return; // was not previously assigned
|
||||
if (!old_value) {
|
||||
return; // was not previously assigned
|
||||
}
|
||||
|
||||
// notify
|
||||
m_notifier.NotifyEntry(entry->local_id, entry->name, old_value,
|
||||
@@ -710,7 +820,9 @@ void Storage::DeleteEntryImpl(Entry* entry, std::unique_lock<wpi::mutex>& lock,
|
||||
// if it had a value, generate message
|
||||
// don't send an update if we don't have an assigned id yet
|
||||
if (local && id != 0xffff) {
|
||||
if (!m_dispatcher) return;
|
||||
if (!m_dispatcher) {
|
||||
return;
|
||||
}
|
||||
auto dispatcher = m_dispatcher;
|
||||
lock.unlock();
|
||||
dispatcher->QueueOutgoing(Message::EntryDelete(id), nullptr, nullptr);
|
||||
@@ -726,7 +838,9 @@ void Storage::DeleteAllEntriesImpl(bool local, F should_delete) {
|
||||
m_notifier.NotifyEntry(entry->local_id, i.getKey(), entry->value,
|
||||
NT_NOTIFY_DELETE | (local ? NT_NOTIFY_LOCAL : 0));
|
||||
// remove it from idmap
|
||||
if (entry->id < m_idmap.size()) m_idmap[entry->id] = nullptr;
|
||||
if (entry->id < m_idmap.size()) {
|
||||
m_idmap[entry->id] = nullptr;
|
||||
}
|
||||
entry->id = 0xffff;
|
||||
entry->local_write = false;
|
||||
entry->value.reset();
|
||||
@@ -743,12 +857,16 @@ void Storage::DeleteAllEntriesImpl(bool local) {
|
||||
|
||||
void Storage::DeleteAllEntries() {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (m_entries.empty()) return;
|
||||
if (m_entries.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeleteAllEntriesImpl(true);
|
||||
|
||||
// generate message
|
||||
if (!m_dispatcher) return;
|
||||
if (!m_dispatcher) {
|
||||
return;
|
||||
}
|
||||
auto dispatcher = m_dispatcher;
|
||||
lock.unlock();
|
||||
dispatcher->QueueOutgoing(Message::ClearEntries(), nullptr, nullptr);
|
||||
@@ -768,8 +886,9 @@ Storage::Entry* Storage::GetOrNew(const Twine& name) {
|
||||
|
||||
unsigned int Storage::GetEntry(const Twine& name) {
|
||||
if (name.isTriviallyEmpty() ||
|
||||
(name.isSingleStringRef() && name.getSingleStringRef().empty()))
|
||||
(name.isSingleStringRef() && name.getSingleStringRef().empty())) {
|
||||
return UINT_MAX;
|
||||
}
|
||||
std::unique_lock lock(m_mutex);
|
||||
return GetOrNew(name)->local_id;
|
||||
}
|
||||
@@ -783,8 +902,12 @@ std::vector<unsigned int> Storage::GetEntries(const Twine& prefix,
|
||||
for (auto& i : m_entries) {
|
||||
Entry* entry = i.getValue();
|
||||
auto value = entry->value.get();
|
||||
if (!value || !i.getKey().startswith(prefixStr)) continue;
|
||||
if (types != 0 && (types & value->type()) == 0) continue;
|
||||
if (!value || !i.getKey().startswith(prefixStr)) {
|
||||
continue;
|
||||
}
|
||||
if (types != 0 && (types & value->type()) == 0) {
|
||||
continue;
|
||||
}
|
||||
ids.push_back(entry->local_id);
|
||||
}
|
||||
return ids;
|
||||
@@ -798,9 +921,13 @@ EntryInfo Storage::GetEntryInfo(int inst, unsigned int local_id) const {
|
||||
info.last_change = 0;
|
||||
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return info;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return info;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
if (!entry->value) return info;
|
||||
if (!entry->value) {
|
||||
return info;
|
||||
}
|
||||
|
||||
info.entry = Handle(inst, local_id, Handle::kEntry);
|
||||
info.name = entry->name;
|
||||
@@ -812,23 +939,33 @@ EntryInfo Storage::GetEntryInfo(int inst, unsigned int local_id) const {
|
||||
|
||||
std::string Storage::GetEntryName(unsigned int local_id) const {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return std::string{};
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return {};
|
||||
}
|
||||
return m_localmap[local_id]->name;
|
||||
}
|
||||
|
||||
NT_Type Storage::GetEntryType(unsigned int local_id) const {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return NT_UNASSIGNED;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return NT_UNASSIGNED;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
if (!entry->value) return NT_UNASSIGNED;
|
||||
if (!entry->value) {
|
||||
return NT_UNASSIGNED;
|
||||
}
|
||||
return entry->value->type();
|
||||
}
|
||||
|
||||
uint64_t Storage::GetEntryLastChange(unsigned int local_id) const {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return 0;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return 0;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
if (!entry->value) return 0;
|
||||
if (!entry->value) {
|
||||
return 0;
|
||||
}
|
||||
return entry->value->last_change();
|
||||
}
|
||||
|
||||
@@ -841,8 +978,12 @@ std::vector<EntryInfo> Storage::GetEntryInfo(int inst, const Twine& prefix,
|
||||
for (auto& i : m_entries) {
|
||||
Entry* entry = i.getValue();
|
||||
auto value = entry->value.get();
|
||||
if (!value || !i.getKey().startswith(prefixStr)) continue;
|
||||
if (types != 0 && (types & value->type()) == 0) continue;
|
||||
if (!value || !i.getKey().startswith(prefixStr)) {
|
||||
continue;
|
||||
}
|
||||
if (types != 0 && (types & value->type()) == 0) {
|
||||
continue;
|
||||
}
|
||||
EntryInfo info;
|
||||
info.entry = Handle(inst, entry->local_id, Handle::kEntry);
|
||||
info.name = i.getKey();
|
||||
@@ -866,7 +1007,9 @@ unsigned int Storage::AddListener(
|
||||
if ((flags & NT_NOTIFY_IMMEDIATE) != 0 && (flags & NT_NOTIFY_NEW) != 0) {
|
||||
for (auto& i : m_entries) {
|
||||
Entry* entry = i.getValue();
|
||||
if (!entry->value || !i.getKey().startswith(prefixStr)) continue;
|
||||
if (!entry->value || !i.getKey().startswith(prefixStr)) {
|
||||
continue;
|
||||
}
|
||||
m_notifier.NotifyEntry(entry->local_id, i.getKey(), entry->value,
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW, uid);
|
||||
}
|
||||
@@ -902,9 +1045,13 @@ unsigned int Storage::AddPolledListener(unsigned int poller,
|
||||
// perform immediate notifications
|
||||
if ((flags & NT_NOTIFY_IMMEDIATE) != 0 && (flags & NT_NOTIFY_NEW) != 0) {
|
||||
for (auto& i : m_entries) {
|
||||
if (!i.getKey().startswith(prefixStr)) continue;
|
||||
if (!i.getKey().startswith(prefixStr)) {
|
||||
continue;
|
||||
}
|
||||
Entry* entry = i.getValue();
|
||||
if (!entry->value) continue;
|
||||
if (!entry->value) {
|
||||
continue;
|
||||
}
|
||||
m_notifier.NotifyEntry(entry->local_id, i.getKey(), entry->value,
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW, uid);
|
||||
}
|
||||
@@ -938,13 +1085,17 @@ bool Storage::GetPersistentEntries(
|
||||
{
|
||||
std::scoped_lock lock(m_mutex);
|
||||
// for periodic, don't re-save unless something has changed
|
||||
if (periodic && !m_persistent_dirty) return false;
|
||||
if (periodic && !m_persistent_dirty) {
|
||||
return false;
|
||||
}
|
||||
m_persistent_dirty = false;
|
||||
entries->reserve(m_entries.size());
|
||||
for (auto& i : m_entries) {
|
||||
Entry* entry = i.getValue();
|
||||
// only write persistent-flagged values
|
||||
if (!entry->value || !entry->IsPersistent()) continue;
|
||||
if (!entry->value || !entry->IsPersistent()) {
|
||||
continue;
|
||||
}
|
||||
entries->emplace_back(i.getKey(), entry->value);
|
||||
}
|
||||
}
|
||||
@@ -971,7 +1122,9 @@ bool Storage::GetEntries(
|
||||
for (auto& i : m_entries) {
|
||||
Entry* entry = i.getValue();
|
||||
// only write values with given prefix
|
||||
if (!entry->value || !i.getKey().startswith(prefixStr)) continue;
|
||||
if (!entry->value || !i.getKey().startswith(prefixStr)) {
|
||||
continue;
|
||||
}
|
||||
entries->emplace_back(i.getKey(), entry->value);
|
||||
}
|
||||
}
|
||||
@@ -988,7 +1141,9 @@ bool Storage::GetEntries(
|
||||
void Storage::CreateRpc(unsigned int local_id, StringRef def,
|
||||
unsigned int rpc_uid) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
|
||||
auto old_value = entry->value;
|
||||
@@ -998,7 +1153,9 @@ void Storage::CreateRpc(unsigned int local_id, StringRef def,
|
||||
// set up the RPC info
|
||||
entry->rpc_uid = rpc_uid;
|
||||
|
||||
if (old_value && *old_value == *value) return;
|
||||
if (old_value && *old_value == *value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// assign an id if it doesn't have one
|
||||
if (entry->id == 0xffff) {
|
||||
@@ -1008,7 +1165,9 @@ void Storage::CreateRpc(unsigned int local_id, StringRef def,
|
||||
}
|
||||
|
||||
// generate message
|
||||
if (!m_dispatcher) return;
|
||||
if (!m_dispatcher) {
|
||||
return;
|
||||
}
|
||||
auto dispatcher = m_dispatcher;
|
||||
if (!old_value || old_value->type() != value->type()) {
|
||||
++entry->seq_num;
|
||||
@@ -1026,13 +1185,19 @@ void Storage::CreateRpc(unsigned int local_id, StringRef def,
|
||||
|
||||
unsigned int Storage::CallRpc(unsigned int local_id, StringRef params) {
|
||||
std::unique_lock lock(m_mutex);
|
||||
if (local_id >= m_localmap.size()) return 0;
|
||||
if (local_id >= m_localmap.size()) {
|
||||
return 0;
|
||||
}
|
||||
Entry* entry = m_localmap[local_id].get();
|
||||
|
||||
if (!entry->value || !entry->value->IsRpc()) return 0;
|
||||
if (!entry->value || !entry->value->IsRpc()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
++entry->rpc_call_uid;
|
||||
if (entry->rpc_call_uid > 0xffff) entry->rpc_call_uid = 0;
|
||||
if (entry->rpc_call_uid > 0xffff) {
|
||||
entry->rpc_call_uid = 0;
|
||||
}
|
||||
unsigned int call_uid = entry->rpc_call_uid;
|
||||
|
||||
auto msg = Message::ExecuteRpc(entry->id, call_uid, params);
|
||||
@@ -1081,7 +1246,9 @@ bool Storage::GetRpcResult(unsigned int local_id, unsigned int call_uid,
|
||||
RpcIdPair call_pair{local_id, call_uid};
|
||||
|
||||
// only allow one blocking call per rpc call uid
|
||||
if (!m_rpc_blocking_calls.insert(call_pair).second) return false;
|
||||
if (!m_rpc_blocking_calls.insert(call_pair).second) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto timeout_time =
|
||||
std::chrono::steady_clock::now() + std::chrono::duration<double>(timeout);
|
||||
|
||||
@@ -43,7 +43,9 @@ class LoadPersistentImpl {
|
||||
std::shared_ptr<Value> ReadStringArrayValue();
|
||||
|
||||
void Warn(const char* msg) {
|
||||
if (m_warn) m_warn(m_line_num, msg);
|
||||
if (m_warn) {
|
||||
m_warn(m_line_num, msg);
|
||||
}
|
||||
}
|
||||
|
||||
wpi::raw_istream& m_is;
|
||||
@@ -71,8 +73,9 @@ class LoadPersistentImpl {
|
||||
static std::pair<wpi::StringRef, wpi::StringRef> ReadStringToken(
|
||||
wpi::StringRef source) {
|
||||
// Match opening quote
|
||||
if (source.empty() || source.front() != '"')
|
||||
if (source.empty() || source.front() != '"') {
|
||||
return std::make_pair(wpi::StringRef(), source);
|
||||
}
|
||||
|
||||
// Scan for ending double quote, checking for escaped as we go.
|
||||
size_t size = source.size();
|
||||
@@ -87,12 +90,13 @@ static std::pair<wpi::StringRef, wpi::StringRef> ReadStringToken(
|
||||
}
|
||||
|
||||
static int fromxdigit(char ch) {
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
if (ch >= 'a' && ch <= 'f') {
|
||||
return (ch - 'a' + 10);
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
} else if (ch >= 'A' && ch <= 'F') {
|
||||
return (ch - 'A' + 10);
|
||||
else
|
||||
} else {
|
||||
return ch - '0';
|
||||
}
|
||||
}
|
||||
|
||||
static wpi::StringRef UnescapeString(wpi::StringRef source,
|
||||
@@ -134,7 +138,9 @@ static wpi::StringRef UnescapeString(wpi::StringRef source,
|
||||
}
|
||||
|
||||
bool LoadPersistentImpl::Load(StringRef prefix, std::vector<Entry>* entries) {
|
||||
if (!ReadHeader()) return false; // header
|
||||
if (!ReadHeader()) {
|
||||
return false; // header
|
||||
}
|
||||
|
||||
while (ReadLine()) {
|
||||
// type
|
||||
@@ -147,7 +153,9 @@ bool LoadPersistentImpl::Load(StringRef prefix, std::vector<Entry>* entries) {
|
||||
// name
|
||||
wpi::SmallString<128> buf;
|
||||
wpi::StringRef name = ReadName(buf);
|
||||
if (name.empty() || !name.startswith(prefix)) continue;
|
||||
if (name.empty() || !name.startswith(prefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// =
|
||||
m_line = m_line.ltrim(" \t");
|
||||
@@ -161,7 +169,9 @@ bool LoadPersistentImpl::Load(StringRef prefix, std::vector<Entry>* entries) {
|
||||
auto value = ReadValue(type);
|
||||
|
||||
// move to entries
|
||||
if (value) entries->emplace_back(name, std::move(value));
|
||||
if (value) {
|
||||
entries->emplace_back(name, std::move(value));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -171,8 +181,9 @@ bool LoadPersistentImpl::ReadLine() {
|
||||
while (!m_is.has_error()) {
|
||||
++m_line_num;
|
||||
m_line = m_is.getline(m_line_buf, INT_MAX).trim();
|
||||
if (!m_line.empty() && m_line.front() != ';' && m_line.front() != '#')
|
||||
if (!m_line.empty() && m_line.front() != ';' && m_line.front() != '#') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -200,12 +211,13 @@ NT_Type LoadPersistentImpl::ReadType() {
|
||||
} else if (tok == "array") {
|
||||
wpi::StringRef array_tok;
|
||||
std::tie(array_tok, m_line) = m_line.split(' ');
|
||||
if (array_tok == "boolean")
|
||||
if (array_tok == "boolean") {
|
||||
return NT_BOOLEAN_ARRAY;
|
||||
else if (array_tok == "double")
|
||||
} else if (array_tok == "double") {
|
||||
return NT_DOUBLE_ARRAY;
|
||||
else if (array_tok == "string")
|
||||
} else if (array_tok == "string") {
|
||||
return NT_STRING_ARRAY;
|
||||
}
|
||||
}
|
||||
return NT_UNASSIGNED;
|
||||
}
|
||||
@@ -247,8 +259,12 @@ std::shared_ptr<Value> LoadPersistentImpl::ReadValue(NT_Type type) {
|
||||
|
||||
std::shared_ptr<Value> LoadPersistentImpl::ReadBooleanValue() {
|
||||
// only true or false is accepted
|
||||
if (m_line == "true") return Value::MakeBoolean(true);
|
||||
if (m_line == "false") return Value::MakeBoolean(false);
|
||||
if (m_line == "true") {
|
||||
return Value::MakeBoolean(true);
|
||||
}
|
||||
if (m_line == "false") {
|
||||
return Value::MakeBoolean(false);
|
||||
}
|
||||
Warn("unrecognized boolean value, not 'true' or 'false'");
|
||||
return nullptr;
|
||||
}
|
||||
@@ -342,7 +358,9 @@ std::shared_ptr<Value> LoadPersistentImpl::ReadStringArrayValue() {
|
||||
m_buf_string_array.push_back(UnescapeString(tok, buf));
|
||||
|
||||
m_line = m_line.ltrim(" \t");
|
||||
if (m_line.empty()) break;
|
||||
if (m_line.empty()) {
|
||||
break;
|
||||
}
|
||||
if (m_line.front() != ',') {
|
||||
Warn("expected comma between strings");
|
||||
return nullptr;
|
||||
@@ -363,7 +381,9 @@ bool Storage::LoadEntries(
|
||||
std::vector<LoadPersistentImpl::Entry> entries;
|
||||
|
||||
// load file
|
||||
if (!LoadPersistentImpl(is, warn).Load(prefixStr, &entries)) return false;
|
||||
if (!LoadPersistentImpl(is, warn).Load(prefixStr, &entries)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy values into storage as quickly as possible so lock isn't held
|
||||
std::vector<std::shared_ptr<Message>> msgs;
|
||||
@@ -373,7 +393,9 @@ bool Storage::LoadEntries(
|
||||
auto old_value = entry->value;
|
||||
entry->value = i.second;
|
||||
bool was_persist = entry->IsPersistent();
|
||||
if (!was_persist && persistent) entry->flags |= NT_PERSISTENT;
|
||||
if (!was_persist && persistent) {
|
||||
entry->flags |= NT_PERSISTENT;
|
||||
}
|
||||
|
||||
// if we're the server, assign an id if it doesn't have one
|
||||
if (m_server && entry->id == 0xffff) {
|
||||
@@ -389,7 +411,9 @@ bool Storage::LoadEntries(
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_LOCAL);
|
||||
} else if (*old_value != *i.second) {
|
||||
unsigned int notify_flags = NT_NOTIFY_UPDATE | NT_NOTIFY_LOCAL;
|
||||
if (!was_persist && persistent) notify_flags |= NT_NOTIFY_FLAGS;
|
||||
if (!was_persist && persistent) {
|
||||
notify_flags |= NT_NOTIFY_FLAGS;
|
||||
}
|
||||
m_notifier.NotifyEntry(entry->local_id, i.first, i.second,
|
||||
notify_flags);
|
||||
} else if (!was_persist && persistent) {
|
||||
@@ -398,7 +422,9 @@ bool Storage::LoadEntries(
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_dispatcher) continue; // shortcut
|
||||
if (!m_dispatcher) {
|
||||
continue; // shortcut
|
||||
}
|
||||
++entry->seq_num;
|
||||
|
||||
// put on update queue
|
||||
@@ -407,19 +433,22 @@ bool Storage::LoadEntries(
|
||||
i.first, entry->id, entry->seq_num.value(), i.second, entry->flags));
|
||||
} else if (entry->id != 0xffff) {
|
||||
// don't send an update if we don't have an assigned id yet
|
||||
if (*old_value != *i.second)
|
||||
if (*old_value != *i.second) {
|
||||
msgs.emplace_back(
|
||||
Message::EntryUpdate(entry->id, entry->seq_num.value(), i.second));
|
||||
if (!was_persist)
|
||||
}
|
||||
if (!was_persist) {
|
||||
msgs.emplace_back(Message::FlagsUpdate(entry->id, entry->flags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_dispatcher) {
|
||||
auto dispatcher = m_dispatcher;
|
||||
lock.unlock();
|
||||
for (auto& msg : msgs)
|
||||
for (auto& msg : msgs) {
|
||||
dispatcher->QueueOutgoing(std::move(msg), nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -430,8 +459,12 @@ const char* Storage::LoadPersistent(
|
||||
std::function<void(size_t line, const char* msg)> warn) {
|
||||
std::error_code ec;
|
||||
wpi::raw_fd_istream is(filename, ec);
|
||||
if (ec.value() != 0) return "could not open file";
|
||||
if (!LoadEntries(is, "", true, warn)) return "error reading file";
|
||||
if (ec.value() != 0) {
|
||||
return "could not open file";
|
||||
}
|
||||
if (!LoadEntries(is, "", true, warn)) {
|
||||
return "error reading file";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -440,7 +473,11 @@ const char* Storage::LoadEntries(
|
||||
std::function<void(size_t line, const char* msg)> warn) {
|
||||
std::error_code ec;
|
||||
wpi::raw_fd_istream is(filename, ec);
|
||||
if (ec.value() != 0) return "could not open file";
|
||||
if (!LoadEntries(is, prefix, false, warn)) return "error reading file";
|
||||
if (ec.value() != 0) {
|
||||
return "could not open file";
|
||||
}
|
||||
if (!LoadEntries(is, prefix, false, warn)) {
|
||||
return "error reading file";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -83,17 +83,21 @@ void SavePersistentImpl::WriteHeader() {
|
||||
|
||||
void SavePersistentImpl::WriteEntries(wpi::ArrayRef<Entry> entries) {
|
||||
for (auto& i : entries) {
|
||||
if (!i.second) continue;
|
||||
if (!i.second) {
|
||||
continue;
|
||||
}
|
||||
WriteEntry(i.first, *i.second);
|
||||
}
|
||||
}
|
||||
|
||||
void SavePersistentImpl::WriteEntry(wpi::StringRef name, const Value& value) {
|
||||
if (!WriteType(value.type())) return; // type
|
||||
WriteString(name); // name
|
||||
m_os << '='; // '='
|
||||
WriteValue(value); // value
|
||||
m_os << '\n'; // eol
|
||||
if (!WriteType(value.type())) {
|
||||
return; // type
|
||||
}
|
||||
WriteString(name); // name
|
||||
m_os << '='; // '='
|
||||
WriteValue(value); // value
|
||||
m_os << '\n'; // eol
|
||||
}
|
||||
|
||||
bool SavePersistentImpl::WriteType(NT_Type type) {
|
||||
@@ -143,7 +147,9 @@ void SavePersistentImpl::WriteValue(const Value& value) {
|
||||
case NT_BOOLEAN_ARRAY: {
|
||||
bool first = true;
|
||||
for (auto elem : value.GetBooleanArray()) {
|
||||
if (!first) m_os << ',';
|
||||
if (!first) {
|
||||
m_os << ',';
|
||||
}
|
||||
first = false;
|
||||
m_os << (elem ? "true" : "false");
|
||||
}
|
||||
@@ -152,7 +158,9 @@ void SavePersistentImpl::WriteValue(const Value& value) {
|
||||
case NT_DOUBLE_ARRAY: {
|
||||
bool first = true;
|
||||
for (auto elem : value.GetDoubleArray()) {
|
||||
if (!first) m_os << ',';
|
||||
if (!first) {
|
||||
m_os << ',';
|
||||
}
|
||||
first = false;
|
||||
m_os << wpi::format("%g", elem);
|
||||
}
|
||||
@@ -161,7 +169,9 @@ void SavePersistentImpl::WriteValue(const Value& value) {
|
||||
case NT_STRING_ARRAY: {
|
||||
bool first = true;
|
||||
for (auto& elem : value.GetStringArray()) {
|
||||
if (!first) m_os << ',';
|
||||
if (!first) {
|
||||
m_os << ',';
|
||||
}
|
||||
first = false;
|
||||
WriteString(elem);
|
||||
}
|
||||
@@ -174,7 +184,9 @@ void SavePersistentImpl::WriteValue(const Value& value) {
|
||||
|
||||
void Storage::SavePersistent(wpi::raw_ostream& os, bool periodic) const {
|
||||
std::vector<SavePersistentImpl::Entry> entries;
|
||||
if (!GetPersistentEntries(periodic, &entries)) return;
|
||||
if (!GetPersistentEntries(periodic, &entries)) {
|
||||
return;
|
||||
}
|
||||
SavePersistentImpl(os).Save(entries);
|
||||
}
|
||||
|
||||
@@ -189,7 +201,9 @@ const char* Storage::SavePersistent(const Twine& filename,
|
||||
|
||||
// Get entries before creating file
|
||||
std::vector<SavePersistentImpl::Entry> entries;
|
||||
if (!GetPersistentEntries(periodic, &entries)) return nullptr;
|
||||
if (!GetPersistentEntries(periodic, &entries)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* err = nullptr;
|
||||
|
||||
@@ -220,13 +234,17 @@ const char* Storage::SavePersistent(const Twine& filename,
|
||||
|
||||
done:
|
||||
// try again if there was an error
|
||||
if (err && periodic) m_persistent_dirty = true;
|
||||
if (err && periodic) {
|
||||
m_persistent_dirty = true;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void Storage::SaveEntries(wpi::raw_ostream& os, const Twine& prefix) const {
|
||||
std::vector<SavePersistentImpl::Entry> entries;
|
||||
if (!GetEntries(prefix, &entries)) return;
|
||||
if (!GetEntries(prefix, &entries)) {
|
||||
return;
|
||||
}
|
||||
SavePersistentImpl(os).Save(entries);
|
||||
}
|
||||
|
||||
@@ -241,7 +259,9 @@ const char* Storage::SaveEntries(const Twine& filename,
|
||||
|
||||
// Get entries before creating file
|
||||
std::vector<SavePersistentImpl::Entry> entries;
|
||||
if (!GetEntries(prefix, &entries)) return nullptr;
|
||||
if (!GetEntries(prefix, &entries)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// start by writing to temporary file
|
||||
std::error_code ec;
|
||||
|
||||
@@ -19,25 +19,28 @@ Value::Value() {
|
||||
|
||||
Value::Value(NT_Type type, uint64_t time, const private_init&) {
|
||||
m_val.type = type;
|
||||
if (time == 0)
|
||||
if (time == 0) {
|
||||
m_val.last_change = wpi::Now();
|
||||
else
|
||||
} else {
|
||||
m_val.last_change = time;
|
||||
if (m_val.type == NT_BOOLEAN_ARRAY)
|
||||
}
|
||||
if (m_val.type == NT_BOOLEAN_ARRAY) {
|
||||
m_val.data.arr_boolean.arr = nullptr;
|
||||
else if (m_val.type == NT_DOUBLE_ARRAY)
|
||||
} else if (m_val.type == NT_DOUBLE_ARRAY) {
|
||||
m_val.data.arr_double.arr = nullptr;
|
||||
else if (m_val.type == NT_STRING_ARRAY)
|
||||
} else if (m_val.type == NT_STRING_ARRAY) {
|
||||
m_val.data.arr_string.arr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Value::~Value() {
|
||||
if (m_val.type == NT_BOOLEAN_ARRAY)
|
||||
if (m_val.type == NT_BOOLEAN_ARRAY) {
|
||||
delete[] m_val.data.arr_boolean.arr;
|
||||
else if (m_val.type == NT_DOUBLE_ARRAY)
|
||||
} else if (m_val.type == NT_DOUBLE_ARRAY) {
|
||||
delete[] m_val.data.arr_double.arr;
|
||||
else if (m_val.type == NT_STRING_ARRAY)
|
||||
} else if (m_val.type == NT_STRING_ARRAY) {
|
||||
delete[] m_val.data.arr_string.arr;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Value> Value::MakeBooleanArray(wpi::ArrayRef<bool> value,
|
||||
@@ -137,8 +140,9 @@ void nt::ConvertToC(const Value& in, NT_Value* out) {
|
||||
auto v = in.GetStringArray();
|
||||
out->data.arr_string.arr = static_cast<NT_String*>(
|
||||
wpi::safe_malloc(v.size() * sizeof(NT_String)));
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
ConvertToC(v[i], &out->data.arr_string.arr[i]);
|
||||
}
|
||||
out->data.arr_string.size = v.size();
|
||||
break;
|
||||
}
|
||||
@@ -179,8 +183,9 @@ std::shared_ptr<Value> nt::ConvertFromC(const NT_Value& value) {
|
||||
case NT_STRING_ARRAY: {
|
||||
std::vector<std::string> v;
|
||||
v.reserve(value.data.arr_string.size);
|
||||
for (size_t i = 0; i < value.data.arr_string.size; ++i)
|
||||
for (size_t i = 0; i < value.data.arr_string.size; ++i) {
|
||||
v.push_back(ConvertFromC(value.data.arr_string.arr[i]));
|
||||
}
|
||||
return Value::MakeStringArray(std::move(v));
|
||||
}
|
||||
default:
|
||||
@@ -190,7 +195,9 @@ std::shared_ptr<Value> nt::ConvertFromC(const NT_Value& value) {
|
||||
}
|
||||
|
||||
bool nt::operator==(const Value& lhs, const Value& rhs) {
|
||||
if (lhs.type() != rhs.type()) return false;
|
||||
if (lhs.type() != rhs.type()) {
|
||||
return false;
|
||||
}
|
||||
switch (lhs.type()) {
|
||||
case NT_UNASSIGNED:
|
||||
return true; // XXX: is this better being false instead?
|
||||
@@ -203,15 +210,17 @@ bool nt::operator==(const Value& lhs, const Value& rhs) {
|
||||
case NT_RPC:
|
||||
return lhs.m_string == rhs.m_string;
|
||||
case NT_BOOLEAN_ARRAY:
|
||||
if (lhs.m_val.data.arr_boolean.size != rhs.m_val.data.arr_boolean.size)
|
||||
if (lhs.m_val.data.arr_boolean.size != rhs.m_val.data.arr_boolean.size) {
|
||||
return false;
|
||||
}
|
||||
return std::memcmp(lhs.m_val.data.arr_boolean.arr,
|
||||
rhs.m_val.data.arr_boolean.arr,
|
||||
lhs.m_val.data.arr_boolean.size *
|
||||
sizeof(lhs.m_val.data.arr_boolean.arr[0])) == 0;
|
||||
case NT_DOUBLE_ARRAY:
|
||||
if (lhs.m_val.data.arr_double.size != rhs.m_val.data.arr_double.size)
|
||||
if (lhs.m_val.data.arr_double.size != rhs.m_val.data.arr_double.size) {
|
||||
return false;
|
||||
}
|
||||
return std::memcmp(lhs.m_val.data.arr_double.arr,
|
||||
rhs.m_val.data.arr_double.arr,
|
||||
lhs.m_val.data.arr_double.size *
|
||||
|
||||
@@ -55,27 +55,37 @@ WireDecoder::WireDecoder(wpi::raw_istream& is, unsigned int proto_rev,
|
||||
m_error = nullptr;
|
||||
}
|
||||
|
||||
WireDecoder::~WireDecoder() { std::free(m_buf); }
|
||||
WireDecoder::~WireDecoder() {
|
||||
std::free(m_buf);
|
||||
}
|
||||
|
||||
bool WireDecoder::ReadDouble(double* val) {
|
||||
const char* buf;
|
||||
if (!Read(&buf, 8)) return false;
|
||||
if (!Read(&buf, 8)) {
|
||||
return false;
|
||||
}
|
||||
*val = ::ReadDouble(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WireDecoder::Realloc(size_t len) {
|
||||
// Double current buffer size until we have enough space.
|
||||
if (m_allocated >= len) return;
|
||||
if (m_allocated >= len) {
|
||||
return;
|
||||
}
|
||||
size_t newlen = m_allocated * 2;
|
||||
while (newlen < len) newlen *= 2;
|
||||
while (newlen < len) {
|
||||
newlen *= 2;
|
||||
}
|
||||
m_buf = static_cast<char*>(wpi::safe_realloc(m_buf, newlen));
|
||||
m_allocated = newlen;
|
||||
}
|
||||
|
||||
bool WireDecoder::ReadType(NT_Type* type) {
|
||||
unsigned int itype;
|
||||
if (!Read8(&itype)) return false;
|
||||
if (!Read8(&itype)) {
|
||||
return false;
|
||||
}
|
||||
// Convert from byte value to enum
|
||||
switch (itype) {
|
||||
case 0x00:
|
||||
@@ -114,17 +124,23 @@ std::shared_ptr<Value> WireDecoder::ReadValue(NT_Type type) {
|
||||
switch (type) {
|
||||
case NT_BOOLEAN: {
|
||||
unsigned int v;
|
||||
if (!Read8(&v)) return nullptr;
|
||||
if (!Read8(&v)) {
|
||||
return nullptr;
|
||||
}
|
||||
return Value::MakeBoolean(v != 0);
|
||||
}
|
||||
case NT_DOUBLE: {
|
||||
double v;
|
||||
if (!ReadDouble(&v)) return nullptr;
|
||||
if (!ReadDouble(&v)) {
|
||||
return nullptr;
|
||||
}
|
||||
return Value::MakeDouble(v);
|
||||
}
|
||||
case NT_STRING: {
|
||||
std::string v;
|
||||
if (!ReadString(&v)) return nullptr;
|
||||
if (!ReadString(&v)) {
|
||||
return nullptr;
|
||||
}
|
||||
return Value::MakeString(std::move(v));
|
||||
}
|
||||
case NT_RAW: {
|
||||
@@ -133,7 +149,9 @@ std::shared_ptr<Value> WireDecoder::ReadValue(NT_Type type) {
|
||||
return nullptr;
|
||||
}
|
||||
std::string v;
|
||||
if (!ReadString(&v)) return nullptr;
|
||||
if (!ReadString(&v)) {
|
||||
return nullptr;
|
||||
}
|
||||
return Value::MakeRaw(std::move(v));
|
||||
}
|
||||
case NT_RPC: {
|
||||
@@ -142,42 +160,60 @@ std::shared_ptr<Value> WireDecoder::ReadValue(NT_Type type) {
|
||||
return nullptr;
|
||||
}
|
||||
std::string v;
|
||||
if (!ReadString(&v)) return nullptr;
|
||||
if (!ReadString(&v)) {
|
||||
return nullptr;
|
||||
}
|
||||
return Value::MakeRpc(std::move(v));
|
||||
}
|
||||
case NT_BOOLEAN_ARRAY: {
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return nullptr;
|
||||
if (!Read8(&size)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// array values
|
||||
const char* buf;
|
||||
if (!Read(&buf, size)) return nullptr;
|
||||
if (!Read(&buf, size)) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<int> v(size);
|
||||
for (unsigned int i = 0; i < size; ++i) v[i] = buf[i] ? 1 : 0;
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
v[i] = buf[i] ? 1 : 0;
|
||||
}
|
||||
return Value::MakeBooleanArray(std::move(v));
|
||||
}
|
||||
case NT_DOUBLE_ARRAY: {
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return nullptr;
|
||||
if (!Read8(&size)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// array values
|
||||
const char* buf;
|
||||
if (!Read(&buf, size * 8)) return nullptr;
|
||||
if (!Read(&buf, size * 8)) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<double> v(size);
|
||||
for (unsigned int i = 0; i < size; ++i) v[i] = ::ReadDouble(buf);
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
v[i] = ::ReadDouble(buf);
|
||||
}
|
||||
return Value::MakeDoubleArray(std::move(v));
|
||||
}
|
||||
case NT_STRING_ARRAY: {
|
||||
// size
|
||||
unsigned int size;
|
||||
if (!Read8(&size)) return nullptr;
|
||||
if (!Read8(&size)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// array values
|
||||
std::vector<std::string> v(size);
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
if (!ReadString(&v[i])) return nullptr;
|
||||
if (!ReadString(&v[i])) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return Value::MakeStringArray(std::move(v));
|
||||
}
|
||||
@@ -191,15 +227,21 @@ bool WireDecoder::ReadString(std::string* str) {
|
||||
size_t len;
|
||||
if (m_proto_rev < 0x0300u) {
|
||||
unsigned int v;
|
||||
if (!Read16(&v)) return false;
|
||||
if (!Read16(&v)) {
|
||||
return false;
|
||||
}
|
||||
len = v;
|
||||
} else {
|
||||
uint64_t v;
|
||||
if (!ReadUleb128(&v)) return false;
|
||||
if (!ReadUleb128(&v)) {
|
||||
return false;
|
||||
}
|
||||
len = v;
|
||||
}
|
||||
const char* buf;
|
||||
if (!Read(&buf, len)) return false;
|
||||
if (!Read(&buf, len)) {
|
||||
return false;
|
||||
}
|
||||
*str = wpi::StringRef(buf, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,9 @@ class WireDecoder {
|
||||
* Caution: the buffer is only temporarily valid.
|
||||
*/
|
||||
bool Read(const char** buf, size_t len) {
|
||||
if (len > m_allocated) Realloc(len);
|
||||
if (len > m_allocated) {
|
||||
Realloc(len);
|
||||
}
|
||||
*buf = m_buf;
|
||||
m_is.read(m_buf, len);
|
||||
#if 0
|
||||
@@ -78,7 +80,9 @@ class WireDecoder {
|
||||
/* Reads a single byte. */
|
||||
bool Read8(unsigned int* val) {
|
||||
const char* buf;
|
||||
if (!Read(&buf, 1)) return false;
|
||||
if (!Read(&buf, 1)) {
|
||||
return false;
|
||||
}
|
||||
*val = (*reinterpret_cast<const unsigned char*>(buf)) & 0xff;
|
||||
return true;
|
||||
}
|
||||
@@ -86,7 +90,9 @@ class WireDecoder {
|
||||
/* Reads a 16-bit word. */
|
||||
bool Read16(unsigned int* val) {
|
||||
const char* buf;
|
||||
if (!Read(&buf, 2)) return false;
|
||||
if (!Read(&buf, 2)) {
|
||||
return false;
|
||||
}
|
||||
unsigned int v = (*reinterpret_cast<const unsigned char*>(buf)) & 0xff;
|
||||
++buf;
|
||||
v <<= 8;
|
||||
@@ -98,7 +104,9 @@ class WireDecoder {
|
||||
/* Reads a 32-bit word. */
|
||||
bool Read32(uint32_t* val) {
|
||||
const char* buf;
|
||||
if (!Read(&buf, 4)) return false;
|
||||
if (!Read(&buf, 4)) {
|
||||
return false;
|
||||
}
|
||||
unsigned int v = (*reinterpret_cast<const unsigned char*>(buf)) & 0xff;
|
||||
++buf;
|
||||
v <<= 8;
|
||||
|
||||
@@ -30,7 +30,9 @@ void WireEncoder::WriteDouble(double val) {
|
||||
static_cast<char>((v >> 8) & 0xff), static_cast<char>(v & 0xff)});
|
||||
}
|
||||
|
||||
void WireEncoder::WriteUleb128(uint32_t val) { wpi::WriteUleb128(m_data, val); }
|
||||
void WireEncoder::WriteUleb128(uint32_t val) {
|
||||
wpi::WriteUleb128(m_data, val);
|
||||
}
|
||||
|
||||
void WireEncoder::WriteType(NT_Type type) {
|
||||
char ch;
|
||||
@@ -84,29 +86,41 @@ size_t WireEncoder::GetValueSize(const Value& value) const {
|
||||
case NT_STRING:
|
||||
return GetStringSize(value.GetString());
|
||||
case NT_RAW:
|
||||
if (m_proto_rev < 0x0300u) return 0;
|
||||
if (m_proto_rev < 0x0300u) {
|
||||
return 0;
|
||||
}
|
||||
return GetStringSize(value.GetRaw());
|
||||
case NT_RPC:
|
||||
if (m_proto_rev < 0x0300u) return 0;
|
||||
if (m_proto_rev < 0x0300u) {
|
||||
return 0;
|
||||
}
|
||||
return GetStringSize(value.GetRpc());
|
||||
case NT_BOOLEAN_ARRAY: {
|
||||
// 1-byte size, 1 byte per element
|
||||
size_t size = value.GetBooleanArray().size();
|
||||
if (size > 0xff) size = 0xff; // size is only 1 byte, truncate
|
||||
if (size > 0xff) {
|
||||
size = 0xff; // size is only 1 byte, truncate
|
||||
}
|
||||
return 1 + size;
|
||||
}
|
||||
case NT_DOUBLE_ARRAY: {
|
||||
// 1-byte size, 8 bytes per element
|
||||
size_t size = value.GetDoubleArray().size();
|
||||
if (size > 0xff) size = 0xff; // size is only 1 byte, truncate
|
||||
if (size > 0xff) {
|
||||
size = 0xff; // size is only 1 byte, truncate
|
||||
}
|
||||
return 1 + size * 8;
|
||||
}
|
||||
case NT_STRING_ARRAY: {
|
||||
auto v = value.GetStringArray();
|
||||
size_t size = v.size();
|
||||
if (size > 0xff) size = 0xff; // size is only 1 byte, truncate
|
||||
size_t len = 1; // 1-byte size
|
||||
for (size_t i = 0; i < size; ++i) len += GetStringSize(v[i]);
|
||||
if (size > 0xff) {
|
||||
size = 0xff; // size is only 1 byte, truncate
|
||||
}
|
||||
size_t len = 1; // 1-byte size
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
len += GetStringSize(v[i]);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
default:
|
||||
@@ -142,28 +156,40 @@ void WireEncoder::WriteValue(const Value& value) {
|
||||
case NT_BOOLEAN_ARRAY: {
|
||||
auto v = value.GetBooleanArray();
|
||||
size_t size = v.size();
|
||||
if (size > 0xff) size = 0xff; // size is only 1 byte, truncate
|
||||
if (size > 0xff) {
|
||||
size = 0xff; // size is only 1 byte, truncate
|
||||
}
|
||||
Write8(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i) Write8(v[i] ? 1 : 0);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
Write8(v[i] ? 1 : 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NT_DOUBLE_ARRAY: {
|
||||
auto v = value.GetDoubleArray();
|
||||
size_t size = v.size();
|
||||
if (size > 0xff) size = 0xff; // size is only 1 byte, truncate
|
||||
if (size > 0xff) {
|
||||
size = 0xff; // size is only 1 byte, truncate
|
||||
}
|
||||
Write8(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i) WriteDouble(v[i]);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
WriteDouble(v[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NT_STRING_ARRAY: {
|
||||
auto v = value.GetStringArray();
|
||||
size_t size = v.size();
|
||||
if (size > 0xff) size = 0xff; // size is only 1 byte, truncate
|
||||
if (size > 0xff) {
|
||||
size = 0xff; // size is only 1 byte, truncate
|
||||
}
|
||||
Write8(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i) WriteString(v[i]);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
WriteString(v[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -175,7 +201,9 @@ void WireEncoder::WriteValue(const Value& value) {
|
||||
size_t WireEncoder::GetStringSize(wpi::StringRef str) const {
|
||||
if (m_proto_rev < 0x0300u) {
|
||||
size_t len = str.size();
|
||||
if (len > 0xffff) len = 0xffff; // Limited to 64K length; truncate
|
||||
if (len > 0xffff) {
|
||||
len = 0xffff; // Limited to 64K length; truncate
|
||||
}
|
||||
return 2 + len;
|
||||
}
|
||||
return wpi::SizeUleb128(str.size()) + str.size();
|
||||
@@ -185,7 +213,9 @@ void WireEncoder::WriteString(wpi::StringRef str) {
|
||||
// length
|
||||
size_t len = str.size();
|
||||
if (m_proto_rev < 0x0300u) {
|
||||
if (len > 0xffff) len = 0xffff; // Limited to 64K length; truncate
|
||||
if (len > 0xffff) {
|
||||
len = 0xffff; // Limited to 64K length; truncate
|
||||
}
|
||||
Write16(len);
|
||||
} else {
|
||||
WriteUleb128(len);
|
||||
|
||||
@@ -64,18 +64,23 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
jvm = vm;
|
||||
|
||||
JNIEnv* env;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
// Cache references to classes
|
||||
for (auto& c : classes) {
|
||||
*c.cls = JClass(env, c.name);
|
||||
if (!*c.cls) return JNI_ERR;
|
||||
if (!*c.cls) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& c : exceptions) {
|
||||
*c.cls = JException(env, c.name);
|
||||
if (!*c.cls) return JNI_ERR;
|
||||
if (!*c.cls) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
@@ -83,8 +88,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
|
||||
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
|
||||
JNIEnv* env;
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
return;
|
||||
}
|
||||
// Delete global references
|
||||
for (auto& c : classes) {
|
||||
c.cls->free(env);
|
||||
@@ -104,40 +110,52 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
|
||||
inline std::shared_ptr<nt::Value> FromJavaRaw(JNIEnv* env, jbyteArray jarr,
|
||||
jlong time) {
|
||||
CriticalJByteArrayRef ref{env, jarr};
|
||||
if (!ref) return nullptr;
|
||||
if (!ref) {
|
||||
return nullptr;
|
||||
}
|
||||
return nt::Value::MakeRaw(ref, time);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<nt::Value> FromJavaRawBB(JNIEnv* env, jobject jbb,
|
||||
int len, jlong time) {
|
||||
JByteArrayRef ref{env, jbb, len};
|
||||
if (!ref) return nullptr;
|
||||
if (!ref) {
|
||||
return nullptr;
|
||||
}
|
||||
return nt::Value::MakeRaw(ref.str(), time);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<nt::Value> FromJavaRpc(JNIEnv* env, jbyteArray jarr,
|
||||
jlong time) {
|
||||
CriticalJByteArrayRef ref{env, jarr};
|
||||
if (!ref) return nullptr;
|
||||
if (!ref) {
|
||||
return nullptr;
|
||||
}
|
||||
return nt::Value::MakeRpc(ref.str(), time);
|
||||
}
|
||||
|
||||
std::shared_ptr<nt::Value> FromJavaBooleanArray(JNIEnv* env, jbooleanArray jarr,
|
||||
jlong time) {
|
||||
CriticalJBooleanArrayRef ref{env, jarr};
|
||||
if (!ref) return nullptr;
|
||||
if (!ref) {
|
||||
return nullptr;
|
||||
}
|
||||
wpi::ArrayRef<jboolean> elements{ref};
|
||||
size_t len = elements.size();
|
||||
std::vector<int> arr;
|
||||
arr.reserve(len);
|
||||
for (size_t i = 0; i < len; ++i) arr.push_back(elements[i]);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
arr.push_back(elements[i]);
|
||||
}
|
||||
return nt::Value::MakeBooleanArray(arr, time);
|
||||
}
|
||||
|
||||
std::shared_ptr<nt::Value> FromJavaDoubleArray(JNIEnv* env, jdoubleArray jarr,
|
||||
jlong time) {
|
||||
CriticalJDoubleArrayRef ref{env, jarr};
|
||||
if (!ref) return nullptr;
|
||||
if (!ref) {
|
||||
return nullptr;
|
||||
}
|
||||
return nt::Value::MakeDoubleArray(ref, time);
|
||||
}
|
||||
|
||||
@@ -149,7 +167,9 @@ std::shared_ptr<nt::Value> FromJavaStringArray(JNIEnv* env, jobjectArray jarr,
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
JLocal<jstring> elem{
|
||||
env, static_cast<jstring>(env->GetObjectArrayElement(jarr, i))};
|
||||
if (!elem) return nullptr;
|
||||
if (!elem) {
|
||||
return nullptr;
|
||||
}
|
||||
arr.push_back(JStringRef{env, elem}.str());
|
||||
}
|
||||
return nt::Value::MakeStringArray(std::move(arr), time);
|
||||
@@ -162,10 +182,12 @@ std::shared_ptr<nt::Value> FromJavaStringArray(JNIEnv* env, jobjectArray jarr,
|
||||
static jobject MakeJObject(JNIEnv* env, const nt::Value& value) {
|
||||
static jmethodID booleanConstructor = nullptr;
|
||||
static jmethodID doubleConstructor = nullptr;
|
||||
if (!booleanConstructor)
|
||||
if (!booleanConstructor) {
|
||||
booleanConstructor = env->GetMethodID(booleanCls, "<init>", "(Z)V");
|
||||
if (!doubleConstructor)
|
||||
}
|
||||
if (!doubleConstructor) {
|
||||
doubleConstructor = env->GetMethodID(doubleCls, "<init>", "(D)V");
|
||||
}
|
||||
|
||||
switch (value.type()) {
|
||||
case NT_BOOLEAN:
|
||||
@@ -194,9 +216,10 @@ static jobject MakeJObject(JNIEnv* env, const nt::Value& value) {
|
||||
static jobject MakeJValue(JNIEnv* env, const nt::Value* value) {
|
||||
static jmethodID constructor =
|
||||
env->GetMethodID(valueCls, "<init>", "(ILjava/lang/Object;J)V");
|
||||
if (!value)
|
||||
if (!value) {
|
||||
return env->NewObject(valueCls, constructor, (jint)NT_UNASSIGNED, nullptr,
|
||||
(jlong)0);
|
||||
}
|
||||
return env->NewObject(valueCls, constructor, (jint)value->type(),
|
||||
MakeJObject(env, *value), (jlong)value->time());
|
||||
}
|
||||
@@ -281,7 +304,9 @@ static jobjectArray MakeJObject(JNIEnv* env, jobject inst,
|
||||
wpi::ArrayRef<nt::ConnectionNotification> arr) {
|
||||
jobjectArray jarr =
|
||||
env->NewObjectArray(arr.size(), connectionNotificationCls, nullptr);
|
||||
if (!jarr) return nullptr;
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> elem{env, MakeJObject(env, inst, arr[i])};
|
||||
env->SetObjectArrayElement(jarr, i, elem.obj());
|
||||
@@ -293,7 +318,9 @@ static jobjectArray MakeJObject(JNIEnv* env, jobject inst,
|
||||
wpi::ArrayRef<nt::EntryNotification> arr) {
|
||||
jobjectArray jarr =
|
||||
env->NewObjectArray(arr.size(), entryNotificationCls, nullptr);
|
||||
if (!jarr) return nullptr;
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> elem{env, MakeJObject(env, inst, arr[i])};
|
||||
env->SetObjectArrayElement(jarr, i, elem.obj());
|
||||
@@ -304,7 +331,9 @@ static jobjectArray MakeJObject(JNIEnv* env, jobject inst,
|
||||
static jobjectArray MakeJObject(JNIEnv* env, jobject inst,
|
||||
wpi::ArrayRef<nt::LogMessage> arr) {
|
||||
jobjectArray jarr = env->NewObjectArray(arr.size(), logMessageCls, nullptr);
|
||||
if (!jarr) return nullptr;
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> elem{env, MakeJObject(env, inst, arr[i])};
|
||||
env->SetObjectArrayElement(jarr, i, elem.obj());
|
||||
@@ -315,7 +344,9 @@ static jobjectArray MakeJObject(JNIEnv* env, jobject inst,
|
||||
static jobjectArray MakeJObject(JNIEnv* env, jobject inst,
|
||||
wpi::ArrayRef<nt::RpcAnswer> arr) {
|
||||
jobjectArray jarr = env->NewObjectArray(arr.size(), rpcAnswerCls, nullptr);
|
||||
if (!jarr) return nullptr;
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> elem{env, MakeJObject(env, inst, arr[i])};
|
||||
env->SetObjectArrayElement(jarr, i, elem.obj());
|
||||
@@ -513,7 +544,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setRaw__IJ_3BZ
|
||||
return false;
|
||||
}
|
||||
auto v = FromJavaRaw(env, value, time);
|
||||
if (!v) return false;
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
if (force) {
|
||||
nt::SetEntryTypeValue(entry, v);
|
||||
return JNI_TRUE;
|
||||
@@ -536,7 +569,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setRaw__IJLjava_nio_ByteBuffer
|
||||
return false;
|
||||
}
|
||||
auto v = FromJavaRawBB(env, value, len, time);
|
||||
if (!v) return false;
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
if (force) {
|
||||
nt::SetEntryTypeValue(entry, v);
|
||||
return JNI_TRUE;
|
||||
@@ -559,7 +594,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setBooleanArray
|
||||
return false;
|
||||
}
|
||||
auto v = FromJavaBooleanArray(env, value, time);
|
||||
if (!v) return false;
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
if (force) {
|
||||
nt::SetEntryTypeValue(entry, v);
|
||||
return JNI_TRUE;
|
||||
@@ -582,7 +619,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setDoubleArray
|
||||
return false;
|
||||
}
|
||||
auto v = FromJavaDoubleArray(env, value, time);
|
||||
if (!v) return false;
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
if (force) {
|
||||
nt::SetEntryTypeValue(entry, v);
|
||||
return JNI_TRUE;
|
||||
@@ -605,7 +644,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setStringArray
|
||||
return false;
|
||||
}
|
||||
auto v = FromJavaStringArray(env, value, time);
|
||||
if (!v) return false;
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
if (force) {
|
||||
nt::SetEntryTypeValue(entry, v);
|
||||
return JNI_TRUE;
|
||||
@@ -636,7 +677,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getBoolean
|
||||
(JNIEnv*, jclass, jint entry, jboolean defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsBoolean()) return defaultValue;
|
||||
if (!val || !val->IsBoolean()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return val->GetBoolean();
|
||||
}
|
||||
|
||||
@@ -650,7 +693,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getDouble
|
||||
(JNIEnv*, jclass, jint entry, jdouble defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsDouble()) return defaultValue;
|
||||
if (!val || !val->IsDouble()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return val->GetDouble();
|
||||
}
|
||||
|
||||
@@ -664,7 +709,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getString
|
||||
(JNIEnv* env, jclass, jint entry, jstring defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsString()) return defaultValue;
|
||||
if (!val || !val->IsString()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return MakeJString(env, val->GetString());
|
||||
}
|
||||
|
||||
@@ -678,7 +725,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getRaw
|
||||
(JNIEnv* env, jclass, jint entry, jbyteArray defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsRaw()) return defaultValue;
|
||||
if (!val || !val->IsRaw()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return MakeJByteArray(env, val->GetRaw());
|
||||
}
|
||||
|
||||
@@ -692,7 +741,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getBooleanArray
|
||||
(JNIEnv* env, jclass, jint entry, jbooleanArray defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsBooleanArray()) return defaultValue;
|
||||
if (!val || !val->IsBooleanArray()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return MakeJBooleanArray(env, val->GetBooleanArray());
|
||||
}
|
||||
|
||||
@@ -706,7 +757,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getDoubleArray
|
||||
(JNIEnv* env, jclass, jint entry, jdoubleArray defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsDoubleArray()) return defaultValue;
|
||||
if (!val || !val->IsDoubleArray()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return MakeJDoubleArray(env, val->GetDoubleArray());
|
||||
}
|
||||
|
||||
@@ -720,7 +773,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getStringArray
|
||||
(JNIEnv* env, jclass, jint entry, jobjectArray defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsStringArray()) return defaultValue;
|
||||
if (!val || !val->IsStringArray()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return MakeJStringArray(env, val->GetStringArray());
|
||||
}
|
||||
|
||||
@@ -911,7 +966,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getEntryInfo
|
||||
}
|
||||
auto arr = nt::GetEntryInfo(inst, JStringRef{env, prefix}.str(), types);
|
||||
jobjectArray jarr = env->NewObjectArray(arr.size(), entryInfoCls, nullptr);
|
||||
if (!jarr) return nullptr;
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> jelem{env, MakeJObject(env, instObject, arr[i])};
|
||||
env->SetObjectArrayElement(jarr, i, jelem);
|
||||
@@ -1291,7 +1348,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getRpcResult__II
|
||||
(JNIEnv* env, jclass, jint entry, jint call)
|
||||
{
|
||||
std::string result;
|
||||
if (!nt::GetRpcResult(entry, call, &result)) return nullptr;
|
||||
if (!nt::GetRpcResult(entry, call, &result)) {
|
||||
return nullptr;
|
||||
}
|
||||
return MakeJByteArray(env, result);
|
||||
}
|
||||
|
||||
@@ -1306,8 +1365,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getRpcResult__IID
|
||||
{
|
||||
std::string result;
|
||||
bool timed_out = false;
|
||||
if (!nt::GetRpcResult(entry, call, &result, timeout, &timed_out))
|
||||
if (!nt::GetRpcResult(entry, call, &result, timeout, &timed_out)) {
|
||||
return nullptr;
|
||||
}
|
||||
return MakeJByteArray(env, result);
|
||||
}
|
||||
|
||||
@@ -1333,7 +1393,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getRpc
|
||||
(JNIEnv* env, jclass, jint entry, jbyteArray defaultValue)
|
||||
{
|
||||
auto val = nt::GetEntryValue(entry);
|
||||
if (!val || !val->IsRpc()) return defaultValue;
|
||||
if (!val || !val->IsRpc()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return MakeJByteArray(env, val->GetRpc());
|
||||
}
|
||||
|
||||
@@ -1475,7 +1537,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_startClient__I_3Ljava_lang_Str
|
||||
return;
|
||||
}
|
||||
jint* portInts = env->GetIntArrayElements(ports, nullptr);
|
||||
if (!portInts) return;
|
||||
if (!portInts) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
std::vector<std::pair<nt::StringRef, unsigned int>> servers;
|
||||
@@ -1560,7 +1624,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setServer__I_3Ljava_lang_Strin
|
||||
return;
|
||||
}
|
||||
jint* portInts = env->GetIntArrayElements(ports, nullptr);
|
||||
if (!portInts) return;
|
||||
if (!portInts) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
std::vector<std::pair<nt::StringRef, unsigned int>> servers;
|
||||
@@ -1653,7 +1719,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_getConnections
|
||||
auto arr = nt::GetConnections(inst);
|
||||
jobjectArray jarr =
|
||||
env->NewObjectArray(arr.size(), connectionInfoCls, nullptr);
|
||||
if (!jarr) return nullptr;
|
||||
if (!jarr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
JLocal<jobject> jelem{env, MakeJObject(env, arr[i])};
|
||||
env->SetObjectArrayElement(jarr, i, jelem);
|
||||
@@ -1687,7 +1755,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_savePersistent
|
||||
return;
|
||||
}
|
||||
const char* err = nt::SavePersistent(inst, JStringRef{env, filename}.str());
|
||||
if (err) persistentEx.Throw(env, err);
|
||||
if (err) {
|
||||
persistentEx.Throw(env, err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1737,7 +1807,9 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_saveEntries
|
||||
}
|
||||
const char* err = nt::SaveEntries(inst, JStringRef{env, filename}.str(),
|
||||
JStringRef{env, prefix}.str());
|
||||
if (err) persistentEx.Throw(env, err);
|
||||
if (err) {
|
||||
persistentEx.Throw(env, err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -31,7 +31,9 @@ unsigned int NetworkTable::s_port = NT_DEFAULT_PORT;
|
||||
|
||||
StringRef NetworkTable::BasenameKey(StringRef key) {
|
||||
size_t slash = key.rfind(PATH_SEPARATOR_CHAR);
|
||||
if (slash == StringRef::npos) return key;
|
||||
if (slash == StringRef::npos) {
|
||||
return key;
|
||||
}
|
||||
return key.substr(slash + 1);
|
||||
}
|
||||
|
||||
@@ -45,7 +47,9 @@ StringRef NetworkTable::NormalizeKey(const Twine& key,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
bool withLeadingSlash) {
|
||||
buf.clear();
|
||||
if (withLeadingSlash) buf.push_back(PATH_SEPARATOR_CHAR);
|
||||
if (withLeadingSlash) {
|
||||
buf.push_back(PATH_SEPARATOR_CHAR);
|
||||
}
|
||||
// for each path element, add it with a slash following
|
||||
wpi::SmallString<128> keyBuf;
|
||||
StringRef keyStr = key.toStringRef(keyBuf);
|
||||
@@ -56,7 +60,9 @@ StringRef NetworkTable::NormalizeKey(const Twine& key,
|
||||
buf.push_back(PATH_SEPARATOR_CHAR);
|
||||
}
|
||||
// remove trailing slash if the input key didn't have one
|
||||
if (!keyStr.empty() && keyStr.back() != PATH_SEPARATOR_CHAR) buf.pop_back();
|
||||
if (!keyStr.empty() && keyStr.back() != PATH_SEPARATOR_CHAR) {
|
||||
buf.pop_back();
|
||||
}
|
||||
return StringRef(buf.data(), buf.size());
|
||||
}
|
||||
|
||||
@@ -85,11 +91,15 @@ std::vector<std::string> NetworkTable::GetHierarchy(const Twine& key) {
|
||||
}
|
||||
|
||||
void NetworkTable::Initialize() {
|
||||
if (s_running) Shutdown();
|
||||
if (s_running) {
|
||||
Shutdown();
|
||||
}
|
||||
auto inst = NetworkTableInstance::GetDefault();
|
||||
if (s_client) {
|
||||
inst.StartClient();
|
||||
if (s_enable_ds) inst.StartDSClient(s_port);
|
||||
if (s_enable_ds) {
|
||||
inst.StartDSClient(s_port);
|
||||
}
|
||||
} else {
|
||||
inst.StartServer(s_persistent_filename, "", s_port);
|
||||
}
|
||||
@@ -97,7 +107,9 @@ void NetworkTable::Initialize() {
|
||||
}
|
||||
|
||||
void NetworkTable::Shutdown() {
|
||||
if (!s_running) return;
|
||||
if (!s_running) {
|
||||
return;
|
||||
}
|
||||
auto inst = NetworkTableInstance::GetDefault();
|
||||
if (s_client) {
|
||||
inst.StopDSClient();
|
||||
@@ -108,14 +120,20 @@ void NetworkTable::Shutdown() {
|
||||
s_running = false;
|
||||
}
|
||||
|
||||
void NetworkTable::SetClientMode() { s_client = true; }
|
||||
void NetworkTable::SetClientMode() {
|
||||
s_client = true;
|
||||
}
|
||||
|
||||
void NetworkTable::SetServerMode() { s_client = false; }
|
||||
void NetworkTable::SetServerMode() {
|
||||
s_client = false;
|
||||
}
|
||||
|
||||
void NetworkTable::SetTeam(int team) {
|
||||
auto inst = NetworkTableInstance::GetDefault();
|
||||
inst.SetServerTeam(team, s_port);
|
||||
if (s_enable_ds) inst.StartDSClient(s_port);
|
||||
if (s_enable_ds) {
|
||||
inst.StartDSClient(s_port);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkTable::SetIPAddress(StringRef address) {
|
||||
@@ -124,35 +142,42 @@ void NetworkTable::SetIPAddress(StringRef address) {
|
||||
inst.SetServer(addr_copy.c_str(), s_port);
|
||||
|
||||
// Stop the DS client if we're explicitly connecting to localhost
|
||||
if (address == "localhost" || address == "127.0.0.1")
|
||||
if (address == "localhost" || address == "127.0.0.1") {
|
||||
inst.StopDSClient();
|
||||
else if (s_enable_ds)
|
||||
} else if (s_enable_ds) {
|
||||
inst.StartDSClient(s_port);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkTable::SetIPAddress(ArrayRef<std::string> addresses) {
|
||||
auto inst = NetworkTableInstance::GetDefault();
|
||||
wpi::SmallVector<StringRef, 8> servers;
|
||||
for (const auto& ip_address : addresses) servers.emplace_back(ip_address);
|
||||
for (const auto& ip_address : addresses) {
|
||||
servers.emplace_back(ip_address);
|
||||
}
|
||||
inst.SetServer(servers, s_port);
|
||||
|
||||
// Stop the DS client if we're explicitly connecting to localhost
|
||||
if (!addresses.empty() &&
|
||||
(addresses[0] == "localhost" || addresses[0] == "127.0.0.1"))
|
||||
(addresses[0] == "localhost" || addresses[0] == "127.0.0.1")) {
|
||||
inst.StopDSClient();
|
||||
else if (s_enable_ds)
|
||||
} else if (s_enable_ds) {
|
||||
inst.StartDSClient(s_port);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkTable::SetPort(unsigned int port) { s_port = port; }
|
||||
void NetworkTable::SetPort(unsigned int port) {
|
||||
s_port = port;
|
||||
}
|
||||
|
||||
void NetworkTable::SetDSClientEnabled(bool enabled) {
|
||||
auto inst = NetworkTableInstance::GetDefault();
|
||||
s_enable_ds = enabled;
|
||||
if (s_enable_ds)
|
||||
if (s_enable_ds) {
|
||||
inst.StartDSClient(s_port);
|
||||
else
|
||||
} else {
|
||||
inst.StopDSClient();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkTable::SetPersistentFilename(StringRef filename) {
|
||||
@@ -167,7 +192,9 @@ void NetworkTable::GlobalDeleteAll() {
|
||||
NetworkTableInstance::GetDefault().DeleteAllEntries();
|
||||
}
|
||||
|
||||
void NetworkTable::Flush() { NetworkTableInstance::GetDefault().Flush(); }
|
||||
void NetworkTable::Flush() {
|
||||
NetworkTableInstance::GetDefault().Flush();
|
||||
}
|
||||
|
||||
void NetworkTable::SetUpdateRate(double interval) {
|
||||
NetworkTableInstance::GetDefault().SetUpdateRate(interval);
|
||||
@@ -184,7 +211,9 @@ const char* NetworkTable::LoadPersistent(
|
||||
}
|
||||
|
||||
std::shared_ptr<NetworkTable> NetworkTable::GetTable(StringRef key) {
|
||||
if (!s_running) Initialize();
|
||||
if (!s_running) {
|
||||
Initialize();
|
||||
}
|
||||
return NetworkTableInstance::GetDefault().GetTable(key);
|
||||
}
|
||||
|
||||
@@ -192,8 +221,12 @@ NetworkTable::NetworkTable(NT_Inst inst, const Twine& path, const private_init&)
|
||||
: m_inst(inst), m_path(path.str()) {}
|
||||
|
||||
NetworkTable::~NetworkTable() {
|
||||
for (auto& i : m_listeners) RemoveEntryListener(i.second);
|
||||
for (auto i : m_lambdaListeners) RemoveEntryListener(i);
|
||||
for (auto& i : m_listeners) {
|
||||
RemoveEntryListener(i.second);
|
||||
}
|
||||
for (auto i : m_lambdaListeners) {
|
||||
RemoveEntryListener(i);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkTableInstance NetworkTable::GetInstance() const {
|
||||
@@ -218,7 +251,9 @@ NT_EntryListener NetworkTable::AddEntryListener(TableEntryListener listener,
|
||||
m_inst, m_path + Twine(PATH_SEPARATOR_CHAR),
|
||||
[=](const EntryNotification& event) {
|
||||
StringRef relative_key = event.name.substr(prefix_len);
|
||||
if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) return;
|
||||
if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) {
|
||||
return;
|
||||
}
|
||||
listener(const_cast<NetworkTable*>(this), relative_key,
|
||||
NetworkTableEntry{event.entry}, event.value, event.flags);
|
||||
},
|
||||
@@ -250,7 +285,9 @@ void NetworkTable::AddTableListener(ITableListener* listener) {
|
||||
void NetworkTable::AddTableListener(ITableListener* listener,
|
||||
bool immediateNotify) {
|
||||
unsigned int flags = NT_NOTIFY_NEW | NT_NOTIFY_UPDATE;
|
||||
if (immediateNotify) flags |= NT_NOTIFY_IMMEDIATE;
|
||||
if (immediateNotify) {
|
||||
flags |= NT_NOTIFY_IMMEDIATE;
|
||||
}
|
||||
AddTableListenerEx(listener, flags);
|
||||
}
|
||||
|
||||
@@ -264,7 +301,9 @@ void NetworkTable::AddTableListenerEx(ITableListener* listener,
|
||||
m_inst, path,
|
||||
[=](const EntryNotification& event) {
|
||||
StringRef relative_key = event.name.substr(prefix_len);
|
||||
if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) return;
|
||||
if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) {
|
||||
return;
|
||||
}
|
||||
listener->ValueChangedEx(this, relative_key, event.value, event.flags);
|
||||
},
|
||||
flags);
|
||||
@@ -274,7 +313,9 @@ void NetworkTable::AddTableListenerEx(ITableListener* listener,
|
||||
void NetworkTable::AddTableListener(StringRef key, ITableListener* listener,
|
||||
bool immediateNotify) {
|
||||
unsigned int flags = NT_NOTIFY_NEW | NT_NOTIFY_UPDATE;
|
||||
if (immediateNotify) flags |= NT_NOTIFY_IMMEDIATE;
|
||||
if (immediateNotify) {
|
||||
flags |= NT_NOTIFY_IMMEDIATE;
|
||||
}
|
||||
AddTableListenerEx(key, listener, flags);
|
||||
}
|
||||
|
||||
@@ -306,16 +347,21 @@ NT_EntryListener NetworkTable::AddSubTableListener(TableListener listener,
|
||||
auto notified_tables = std::make_shared<wpi::StringMap<char>>();
|
||||
|
||||
unsigned int flags = NT_NOTIFY_NEW | NT_NOTIFY_IMMEDIATE;
|
||||
if (localNotify) flags |= NT_NOTIFY_LOCAL;
|
||||
if (localNotify) {
|
||||
flags |= NT_NOTIFY_LOCAL;
|
||||
}
|
||||
NT_EntryListener id = nt::AddEntryListener(
|
||||
m_inst, m_path + Twine(PATH_SEPARATOR_CHAR),
|
||||
[=](const EntryNotification& event) {
|
||||
StringRef relative_key = event.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())
|
||||
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(this, sub_table_key, this->GetSubTable(sub_table_key));
|
||||
},
|
||||
@@ -341,16 +387,21 @@ void NetworkTable::AddSubTableListener(ITableListener* listener,
|
||||
auto notified_tables = std::make_shared<wpi::StringMap<char>>();
|
||||
|
||||
unsigned int flags = NT_NOTIFY_NEW | NT_NOTIFY_IMMEDIATE;
|
||||
if (localNotify) flags |= NT_NOTIFY_LOCAL;
|
||||
if (localNotify) {
|
||||
flags |= NT_NOTIFY_LOCAL;
|
||||
}
|
||||
NT_EntryListener id = nt::AddEntryListener(
|
||||
m_inst, m_path + Twine(PATH_SEPARATOR_CHAR),
|
||||
[=](const EntryNotification& event) {
|
||||
StringRef relative_key = event.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())
|
||||
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->ValueChangedEx(this, sub_table_key, nullptr, event.flags);
|
||||
},
|
||||
@@ -364,8 +415,9 @@ void NetworkTable::RemoveTableListener(ITableListener* listener) {
|
||||
std::remove_if(m_listeners.begin(), m_listeners.end(),
|
||||
[=](const Listener& x) { return x.first == listener; });
|
||||
|
||||
for (auto i = matches_begin; i != m_listeners.end(); ++i)
|
||||
for (auto i = matches_begin; i != m_listeners.end(); ++i) {
|
||||
RemoveEntryListener(i->second);
|
||||
}
|
||||
m_listeners.erase(matches_begin, m_listeners.end());
|
||||
}
|
||||
|
||||
@@ -377,8 +429,9 @@ std::shared_ptr<NetworkTable> NetworkTable::GetSubTable(
|
||||
|
||||
bool NetworkTable::ContainsKey(const Twine& key) const {
|
||||
if (key.isTriviallyEmpty() ||
|
||||
(key.isSingleStringRef() && key.getSingleStringRef().empty()))
|
||||
(key.isSingleStringRef() && key.getSingleStringRef().empty())) {
|
||||
return false;
|
||||
}
|
||||
return GetEntry(key).Exists();
|
||||
}
|
||||
|
||||
@@ -397,7 +450,9 @@ std::vector<std::string> NetworkTable::GetKeys(int types) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
for (auto& info : infos) {
|
||||
auto relative_key = StringRef(info.name).substr(prefix_len);
|
||||
if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) continue;
|
||||
if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) {
|
||||
continue;
|
||||
}
|
||||
keys.push_back(relative_key);
|
||||
m_entries[relative_key] = info.entry;
|
||||
}
|
||||
@@ -411,7 +466,9 @@ std::vector<std::string> NetworkTable::GetSubTables() const {
|
||||
GetEntryInfo(m_inst, m_path + Twine(PATH_SEPARATOR_CHAR), 0)) {
|
||||
auto relative_key = StringRef(entry.name).substr(prefix_len);
|
||||
size_t end_subtable = relative_key.find(PATH_SEPARATOR_CHAR);
|
||||
if (end_subtable == StringRef::npos) continue;
|
||||
if (end_subtable == StringRef::npos) {
|
||||
continue;
|
||||
}
|
||||
keys.push_back(relative_key.substr(0, end_subtable));
|
||||
}
|
||||
return keys;
|
||||
@@ -441,7 +498,9 @@ unsigned int NetworkTable::GetFlags(StringRef key) const {
|
||||
return GetEntry(key).GetFlags();
|
||||
}
|
||||
|
||||
void NetworkTable::Delete(const Twine& key) { GetEntry(key).Delete(); }
|
||||
void NetworkTable::Delete(const Twine& key) {
|
||||
GetEntry(key).Delete();
|
||||
}
|
||||
|
||||
bool NetworkTable::PutNumber(StringRef key, double value) {
|
||||
return GetEntry(key).SetDouble(value);
|
||||
@@ -547,7 +606,9 @@ std::shared_ptr<Value> NetworkTable::GetValue(const Twine& key) const {
|
||||
return GetEntry(key).GetValue();
|
||||
}
|
||||
|
||||
StringRef NetworkTable::GetPath() const { return m_path; }
|
||||
StringRef NetworkTable::GetPath() const {
|
||||
return m_path;
|
||||
}
|
||||
|
||||
const char* NetworkTable::SaveEntries(const Twine& filename) const {
|
||||
return nt::SaveEntries(m_inst, filename, m_path + Twine(PATH_SEPARATOR_CHAR));
|
||||
|
||||
@@ -12,7 +12,9 @@ std::shared_ptr<NetworkTable> NetworkTableInstance::GetTable(
|
||||
const Twine& key) const {
|
||||
StringRef simple;
|
||||
bool isSimple = key.isSingleStringRef();
|
||||
if (isSimple) simple = key.getSingleStringRef();
|
||||
if (isSimple) {
|
||||
simple = key.getSingleStringRef();
|
||||
}
|
||||
if (isSimple && (simple.empty() || simple == "/")) {
|
||||
return std::make_shared<NetworkTable>(m_handle, "",
|
||||
NetworkTable::private_init{});
|
||||
@@ -29,16 +31,18 @@ std::shared_ptr<NetworkTable> NetworkTableInstance::GetTable(
|
||||
void NetworkTableInstance::StartClient(ArrayRef<StringRef> servers,
|
||||
unsigned int port) {
|
||||
wpi::SmallVector<std::pair<StringRef, unsigned int>, 8> server_ports;
|
||||
for (const auto& server : servers)
|
||||
for (const auto& server : servers) {
|
||||
server_ports.emplace_back(std::make_pair(server, port));
|
||||
}
|
||||
StartClient(server_ports);
|
||||
}
|
||||
|
||||
void NetworkTableInstance::SetServer(ArrayRef<StringRef> servers,
|
||||
unsigned int port) {
|
||||
wpi::SmallVector<std::pair<StringRef, unsigned int>, 8> server_ports;
|
||||
for (const auto& server : servers)
|
||||
for (const auto& server : servers) {
|
||||
server_ports.emplace_back(std::make_pair(server, port));
|
||||
}
|
||||
SetServer(server_ports);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,14 +56,16 @@ static void ConvertToC(const RpcDefinition& in, NT_RpcDefinition* out) {
|
||||
out->num_params = in.params.size();
|
||||
out->params = static_cast<NT_RpcParamDef*>(
|
||||
wpi::safe_malloc(in.params.size() * sizeof(NT_RpcParamDef)));
|
||||
for (size_t i = 0; i < in.params.size(); ++i)
|
||||
for (size_t i = 0; i < in.params.size(); ++i) {
|
||||
ConvertToC(in.params[i], &out->params[i]);
|
||||
}
|
||||
|
||||
out->num_results = in.results.size();
|
||||
out->results = static_cast<NT_RpcResultDef*>(
|
||||
wpi::safe_malloc(in.results.size() * sizeof(NT_RpcResultDef)));
|
||||
for (size_t i = 0; i < in.results.size(); ++i)
|
||||
for (size_t i = 0; i < in.results.size(); ++i) {
|
||||
ConvertToC(in.results[i], &out->results[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ConvertToC(const RpcAnswer& in, NT_RpcAnswer* out) {
|
||||
@@ -99,11 +101,17 @@ static void ConvertToC(const LogMessage& in, NT_LogMessage* out) {
|
||||
|
||||
template <typename O, typename I>
|
||||
static O* ConvertToC(const std::vector<I>& in, size_t* out_len) {
|
||||
if (!out_len) return nullptr;
|
||||
if (!out_len) {
|
||||
return nullptr;
|
||||
}
|
||||
*out_len = in.size();
|
||||
if (in.empty()) return nullptr;
|
||||
if (in.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
O* out = static_cast<O*>(wpi::safe_malloc(sizeof(O) * in.size()));
|
||||
for (size_t i = 0; i < in.size(); ++i) ConvertToC(in[i], &out[i]);
|
||||
for (size_t i = 0; i < in.size(); ++i) {
|
||||
ConvertToC(in[i], &out[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -112,7 +120,9 @@ static void DisposeConnectionInfo(NT_ConnectionInfo* info) {
|
||||
std::free(info->remote_ip.str);
|
||||
}
|
||||
|
||||
static void DisposeEntryInfo(NT_EntryInfo* info) { std::free(info->name.str); }
|
||||
static void DisposeEntryInfo(NT_EntryInfo* info) {
|
||||
std::free(info->name.str);
|
||||
}
|
||||
|
||||
static void DisposeEntryNotification(NT_EntryNotification* info) {
|
||||
std::free(info->name.str);
|
||||
@@ -143,12 +153,14 @@ static RpcDefinition ConvertFromC(const NT_RpcDefinition& in) {
|
||||
out.name = ConvertFromC(in.name);
|
||||
|
||||
out.params.reserve(in.num_params);
|
||||
for (size_t i = 0; i < in.num_params; ++i)
|
||||
for (size_t i = 0; i < in.num_params; ++i) {
|
||||
out.params.push_back(ConvertFromC(in.params[i]));
|
||||
}
|
||||
|
||||
out.results.reserve(in.num_results);
|
||||
for (size_t i = 0; i < in.num_results; ++i)
|
||||
for (size_t i = 0; i < in.num_results; ++i) {
|
||||
out.results.push_back(ConvertFromC(in.results[i]));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -159,11 +171,17 @@ extern "C" {
|
||||
* Instance Functions
|
||||
*/
|
||||
|
||||
NT_Inst NT_GetDefaultInstance(void) { return nt::GetDefaultInstance(); }
|
||||
NT_Inst NT_GetDefaultInstance(void) {
|
||||
return nt::GetDefaultInstance();
|
||||
}
|
||||
|
||||
NT_Inst NT_CreateInstance(void) { return nt::CreateInstance(); }
|
||||
NT_Inst NT_CreateInstance(void) {
|
||||
return nt::CreateInstance();
|
||||
}
|
||||
|
||||
void NT_DestroyInstance(NT_Inst inst) { return nt::DestroyInstance(inst); }
|
||||
void NT_DestroyInstance(NT_Inst inst) {
|
||||
return nt::DestroyInstance(inst);
|
||||
}
|
||||
|
||||
NT_Inst NT_GetInstanceFromHandle(NT_Handle handle) {
|
||||
return nt::GetInstanceFromHandle(handle);
|
||||
@@ -181,7 +199,9 @@ NT_Entry* NT_GetEntries(NT_Inst inst, const char* prefix, size_t prefix_len,
|
||||
unsigned int types, size_t* count) {
|
||||
auto info_v = nt::GetEntries(inst, StringRef(prefix, prefix_len), types);
|
||||
*count = info_v.size();
|
||||
if (info_v.size() == 0) return nullptr;
|
||||
if (info_v.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// create array and copy into it
|
||||
NT_Entry* info = static_cast<NT_Entry*>(
|
||||
@@ -197,7 +217,9 @@ char* NT_GetEntryName(NT_Entry entry, size_t* name_len) {
|
||||
return v_name.str;
|
||||
}
|
||||
|
||||
enum NT_Type NT_GetEntryType(NT_Entry entry) { return nt::GetEntryType(entry); }
|
||||
enum NT_Type NT_GetEntryType(NT_Entry entry) {
|
||||
return nt::GetEntryType(entry);
|
||||
}
|
||||
|
||||
uint64_t NT_GetEntryLastChange(NT_Entry entry) {
|
||||
return nt::GetEntryLastChange(entry);
|
||||
@@ -206,7 +228,9 @@ uint64_t NT_GetEntryLastChange(NT_Entry entry) {
|
||||
void NT_GetEntryValue(NT_Entry entry, struct NT_Value* value) {
|
||||
NT_InitValue(value);
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v) return;
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
ConvertToC(*v, value);
|
||||
}
|
||||
|
||||
@@ -231,9 +255,13 @@ unsigned int NT_GetEntryFlags(NT_Entry entry) {
|
||||
return nt::GetEntryFlags(entry);
|
||||
}
|
||||
|
||||
void NT_DeleteEntry(NT_Entry entry) { nt::DeleteEntry(entry); }
|
||||
void NT_DeleteEntry(NT_Entry entry) {
|
||||
nt::DeleteEntry(entry);
|
||||
}
|
||||
|
||||
void NT_DeleteAllEntries(NT_Inst inst) { nt::DeleteAllEntries(inst); }
|
||||
void NT_DeleteAllEntries(NT_Inst inst) {
|
||||
nt::DeleteAllEntries(inst);
|
||||
}
|
||||
|
||||
struct NT_EntryInfo* NT_GetEntryInfo(NT_Inst inst, const char* prefix,
|
||||
size_t prefix_len, unsigned int types,
|
||||
@@ -244,7 +272,9 @@ struct NT_EntryInfo* NT_GetEntryInfo(NT_Inst inst, const char* prefix,
|
||||
|
||||
NT_Bool NT_GetEntryInfoHandle(NT_Entry entry, struct NT_EntryInfo* info) {
|
||||
auto info_v = nt::GetEntryInfo(entry);
|
||||
if (info_v.name.empty()) return false;
|
||||
if (info_v.name.empty()) {
|
||||
return false;
|
||||
}
|
||||
ConvertToC(info_v, info);
|
||||
return true;
|
||||
}
|
||||
@@ -425,7 +455,9 @@ NT_RpcAnswer* NT_PollRpcTimeout(NT_RpcCallPoller poller, size_t* len,
|
||||
return ConvertToC<NT_RpcAnswer>(arr_cpp, len);
|
||||
}
|
||||
|
||||
void NT_CancelPollRpc(NT_RpcCallPoller poller) { nt::CancelPollRpc(poller); }
|
||||
void NT_CancelPollRpc(NT_RpcCallPoller poller) {
|
||||
nt::CancelPollRpc(poller);
|
||||
}
|
||||
|
||||
NT_Bool NT_WaitForRpcCallQueue(NT_Inst inst, double timeout) {
|
||||
return nt::WaitForRpcCallQueue(inst, timeout);
|
||||
@@ -442,7 +474,9 @@ NT_RpcCall NT_CallRpc(NT_Entry entry, const char* params, size_t params_len) {
|
||||
|
||||
char* NT_GetRpcResult(NT_Entry entry, NT_RpcCall call, size_t* result_len) {
|
||||
std::string result;
|
||||
if (!nt::GetRpcResult(entry, call, &result)) return nullptr;
|
||||
if (!nt::GetRpcResult(entry, call, &result)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// convert result
|
||||
*result_len = result.size();
|
||||
@@ -486,7 +520,9 @@ char* NT_PackRpcDefinition(const NT_RpcDefinition* def, size_t* packed_len) {
|
||||
NT_Bool NT_UnpackRpcDefinition(const char* packed, size_t packed_len,
|
||||
NT_RpcDefinition* def) {
|
||||
nt::RpcDefinition def_v;
|
||||
if (!nt::UnpackRpcDefinition(StringRef(packed, packed_len), &def_v)) return 0;
|
||||
if (!nt::UnpackRpcDefinition(StringRef(packed, packed_len), &def_v)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert result
|
||||
ConvertToC(def_v, def);
|
||||
@@ -498,8 +534,9 @@ char* NT_PackRpcValues(const NT_Value** values, size_t values_len,
|
||||
// create input vector
|
||||
std::vector<std::shared_ptr<Value>> values_v;
|
||||
values_v.reserve(values_len);
|
||||
for (size_t i = 0; i < values_len; ++i)
|
||||
for (size_t i = 0; i < values_len; ++i) {
|
||||
values_v.push_back(ConvertFromC(*values[i]));
|
||||
}
|
||||
|
||||
// make the call
|
||||
auto packed = nt::PackRpcValues(values_v);
|
||||
@@ -515,7 +552,9 @@ NT_Value** NT_UnpackRpcValues(const char* packed, size_t packed_len,
|
||||
const NT_Type* types, size_t types_len) {
|
||||
auto values_v = nt::UnpackRpcValues(StringRef(packed, packed_len),
|
||||
ArrayRef<NT_Type>(types, types_len));
|
||||
if (values_v.size() == 0) return nullptr;
|
||||
if (values_v.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// create array and copy into it
|
||||
NT_Value** values = static_cast<NT_Value**>(
|
||||
@@ -539,18 +578,26 @@ unsigned int NT_GetNetworkMode(NT_Inst inst) {
|
||||
return nt::GetNetworkMode(inst);
|
||||
}
|
||||
|
||||
void NT_StartLocal(NT_Inst inst) { nt::StartLocal(inst); }
|
||||
void NT_StartLocal(NT_Inst inst) {
|
||||
nt::StartLocal(inst);
|
||||
}
|
||||
|
||||
void NT_StopLocal(NT_Inst inst) { nt::StopLocal(inst); }
|
||||
void NT_StopLocal(NT_Inst inst) {
|
||||
nt::StopLocal(inst);
|
||||
}
|
||||
|
||||
void NT_StartServer(NT_Inst inst, const char* persist_filename,
|
||||
const char* listen_address, unsigned int port) {
|
||||
nt::StartServer(inst, persist_filename, listen_address, port);
|
||||
}
|
||||
|
||||
void NT_StopServer(NT_Inst inst) { nt::StopServer(inst); }
|
||||
void NT_StopServer(NT_Inst inst) {
|
||||
nt::StopServer(inst);
|
||||
}
|
||||
|
||||
void NT_StartClientNone(NT_Inst inst) { nt::StartClient(inst); }
|
||||
void NT_StartClientNone(NT_Inst inst) {
|
||||
nt::StartClient(inst);
|
||||
}
|
||||
|
||||
void NT_StartClient(NT_Inst inst, const char* server_name, unsigned int port) {
|
||||
nt::StartClient(inst, server_name, port);
|
||||
@@ -560,8 +607,9 @@ void NT_StartClientMulti(NT_Inst inst, size_t count, const char** server_names,
|
||||
const unsigned int* ports) {
|
||||
std::vector<std::pair<StringRef, unsigned int>> servers;
|
||||
servers.reserve(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
servers.emplace_back(std::make_pair(server_names[i], ports[i]));
|
||||
}
|
||||
nt::StartClient(inst, servers);
|
||||
}
|
||||
|
||||
@@ -569,7 +617,9 @@ void NT_StartClientTeam(NT_Inst inst, unsigned int team, unsigned int port) {
|
||||
nt::StartClientTeam(inst, team, port);
|
||||
}
|
||||
|
||||
void NT_StopClient(NT_Inst inst) { nt::StopClient(inst); }
|
||||
void NT_StopClient(NT_Inst inst) {
|
||||
nt::StopClient(inst);
|
||||
}
|
||||
|
||||
void NT_SetServer(NT_Inst inst, const char* server_name, unsigned int port) {
|
||||
nt::SetServer(inst, server_name, port);
|
||||
@@ -579,8 +629,9 @@ void NT_SetServerMulti(NT_Inst inst, size_t count, const char** server_names,
|
||||
const unsigned int* ports) {
|
||||
std::vector<std::pair<StringRef, unsigned int>> servers;
|
||||
servers.reserve(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
servers.emplace_back(std::make_pair(server_names[i], ports[i]));
|
||||
}
|
||||
nt::SetServer(inst, servers);
|
||||
}
|
||||
|
||||
@@ -592,15 +643,21 @@ void NT_StartDSClient(NT_Inst inst, unsigned int port) {
|
||||
nt::StartDSClient(inst, port);
|
||||
}
|
||||
|
||||
void NT_StopDSClient(NT_Inst inst) { nt::StopDSClient(inst); }
|
||||
void NT_StopDSClient(NT_Inst inst) {
|
||||
nt::StopDSClient(inst);
|
||||
}
|
||||
|
||||
void NT_SetUpdateRate(NT_Inst inst, double interval) {
|
||||
nt::SetUpdateRate(inst, interval);
|
||||
}
|
||||
|
||||
void NT_Flush(NT_Inst inst) { nt::Flush(inst); }
|
||||
void NT_Flush(NT_Inst inst) {
|
||||
nt::Flush(inst);
|
||||
}
|
||||
|
||||
NT_Bool NT_IsConnected(NT_Inst inst) { return nt::IsConnected(inst); }
|
||||
NT_Bool NT_IsConnected(NT_Inst inst) {
|
||||
return nt::IsConnected(inst);
|
||||
}
|
||||
|
||||
struct NT_ConnectionInfo* NT_GetConnections(NT_Inst inst, size_t* count) {
|
||||
auto conn_v = nt::GetConnections(inst);
|
||||
@@ -635,7 +692,9 @@ const char* NT_LoadEntries(NT_Inst inst, const char* filename,
|
||||
* Utility Functions
|
||||
*/
|
||||
|
||||
uint64_t NT_Now(void) { return wpi::Now(); }
|
||||
uint64_t NT_Now(void) {
|
||||
return wpi::Now();
|
||||
}
|
||||
|
||||
NT_Logger NT_AddLogger(NT_Inst inst, void* data, NT_LogFunc func,
|
||||
unsigned int min_level, unsigned int max_level) {
|
||||
@@ -680,7 +739,9 @@ void NT_CancelPollLogger(NT_LoggerPoller poller) {
|
||||
nt::CancelPollLogger(poller);
|
||||
}
|
||||
|
||||
void NT_RemoveLogger(NT_Logger logger) { nt::RemoveLogger(logger); }
|
||||
void NT_RemoveLogger(NT_Logger logger) {
|
||||
nt::RemoveLogger(logger);
|
||||
}
|
||||
|
||||
NT_Bool NT_WaitForLoggerQueue(NT_Inst inst, double timeout) {
|
||||
return nt::WaitForLoggerQueue(inst, timeout);
|
||||
@@ -704,8 +765,9 @@ void NT_DisposeValue(NT_Value* value) {
|
||||
std::free(value->data.arr_double.arr);
|
||||
break;
|
||||
case NT_STRING_ARRAY: {
|
||||
for (size_t i = 0; i < value->data.arr_string.size; i++)
|
||||
for (size_t i = 0; i < value->data.arr_string.size; i++) {
|
||||
std::free(value->data.arr_string.arr[i].str);
|
||||
}
|
||||
std::free(value->data.arr_string.arr);
|
||||
break;
|
||||
}
|
||||
@@ -732,22 +794,32 @@ void NT_InitString(NT_String* str) {
|
||||
str->len = 0;
|
||||
}
|
||||
|
||||
void NT_DisposeEntryArray(NT_Entry* arr, size_t /*count*/) { std::free(arr); }
|
||||
void NT_DisposeEntryArray(NT_Entry* arr, size_t /*count*/) {
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_DisposeConnectionInfoArray(NT_ConnectionInfo* arr, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) DisposeConnectionInfo(&arr[i]);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
DisposeConnectionInfo(&arr[i]);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_DisposeEntryInfoArray(NT_EntryInfo* arr, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) DisposeEntryInfo(&arr[i]);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
DisposeEntryInfo(&arr[i]);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_DisposeEntryInfo(NT_EntryInfo* info) { DisposeEntryInfo(info); }
|
||||
void NT_DisposeEntryInfo(NT_EntryInfo* info) {
|
||||
DisposeEntryInfo(info);
|
||||
}
|
||||
|
||||
void NT_DisposeEntryNotificationArray(NT_EntryNotification* arr, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) DisposeEntryNotification(&arr[i]);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
DisposeEntryNotification(&arr[i]);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
@@ -757,7 +829,9 @@ void NT_DisposeEntryNotification(NT_EntryNotification* info) {
|
||||
|
||||
void NT_DisposeConnectionNotificationArray(NT_ConnectionNotification* arr,
|
||||
size_t count) {
|
||||
for (size_t i = 0; i < count; i++) DisposeConnectionNotification(&arr[i]);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
DisposeConnectionNotification(&arr[i]);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
@@ -766,11 +840,15 @@ void NT_DisposeConnectionNotification(NT_ConnectionNotification* info) {
|
||||
}
|
||||
|
||||
void NT_DisposeLogMessageArray(NT_LogMessage* arr, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) NT_DisposeLogMessage(&arr[i]);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
NT_DisposeLogMessage(&arr[i]);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
void NT_DisposeLogMessage(NT_LogMessage* info) { std::free(info->message); }
|
||||
void NT_DisposeLogMessage(NT_LogMessage* info) {
|
||||
std::free(info->message);
|
||||
}
|
||||
|
||||
void NT_DisposeRpcDefinition(NT_RpcDefinition* def) {
|
||||
NT_DisposeString(&def->name);
|
||||
@@ -783,15 +861,18 @@ void NT_DisposeRpcDefinition(NT_RpcDefinition* def) {
|
||||
def->params = nullptr;
|
||||
def->num_params = 0;
|
||||
|
||||
for (size_t i = 0; i < def->num_results; ++i)
|
||||
for (size_t i = 0; i < def->num_results; ++i) {
|
||||
NT_DisposeString(&def->results[i].name);
|
||||
}
|
||||
std::free(def->results);
|
||||
def->results = nullptr;
|
||||
def->num_results = 0;
|
||||
}
|
||||
|
||||
void NT_DisposeRpcAnswerArray(NT_RpcAnswer* arr, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) NT_DisposeRpcAnswer(&arr[i]);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
NT_DisposeRpcAnswer(&arr[i]);
|
||||
}
|
||||
std::free(arr);
|
||||
}
|
||||
|
||||
@@ -831,11 +912,19 @@ struct NT_String* NT_AllocateStringArray(size_t size) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void NT_FreeCharArray(char* v_char) { std::free(v_char); }
|
||||
void NT_FreeDoubleArray(double* v_double) { std::free(v_double); }
|
||||
void NT_FreeBooleanArray(int* v_boolean) { std::free(v_boolean); }
|
||||
void NT_FreeCharArray(char* v_char) {
|
||||
std::free(v_char);
|
||||
}
|
||||
void NT_FreeDoubleArray(double* v_double) {
|
||||
std::free(v_double);
|
||||
}
|
||||
void NT_FreeBooleanArray(int* v_boolean) {
|
||||
std::free(v_boolean);
|
||||
}
|
||||
void NT_FreeStringArray(struct NT_String* v_string, size_t arr_size) {
|
||||
for (size_t i = 0; i < arr_size; i++) std::free(v_string[i].str);
|
||||
for (size_t i = 0; i < arr_size; i++) {
|
||||
std::free(v_string[i].str);
|
||||
}
|
||||
std::free(v_string);
|
||||
}
|
||||
|
||||
@@ -912,7 +1001,9 @@ NT_Bool NT_SetEntryStringArray(NT_Entry entry, uint64_t time,
|
||||
NT_Bool force) {
|
||||
std::vector<std::string> v;
|
||||
v.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) v.push_back(ConvertFromC(arr[i]));
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
v.push_back(ConvertFromC(arr[i]));
|
||||
}
|
||||
|
||||
if (force != 0) {
|
||||
nt::SetEntryTypeValue(entry, Value::MakeStringArray(std::move(v), time));
|
||||
@@ -923,13 +1014,17 @@ NT_Bool NT_SetEntryStringArray(NT_Entry entry, uint64_t time,
|
||||
}
|
||||
|
||||
enum NT_Type NT_GetValueType(const struct NT_Value* value) {
|
||||
if (!value) return NT_Type::NT_UNASSIGNED;
|
||||
if (!value) {
|
||||
return NT_Type::NT_UNASSIGNED;
|
||||
}
|
||||
return value->type;
|
||||
}
|
||||
|
||||
NT_Bool NT_GetValueBoolean(const struct NT_Value* value, uint64_t* last_change,
|
||||
NT_Bool* v_boolean) {
|
||||
if (!value || value->type != NT_Type::NT_BOOLEAN) return 0;
|
||||
if (!value || value->type != NT_Type::NT_BOOLEAN) {
|
||||
return 0;
|
||||
}
|
||||
*v_boolean = value->data.v_boolean;
|
||||
*last_change = value->last_change;
|
||||
return 1;
|
||||
@@ -937,7 +1032,9 @@ NT_Bool NT_GetValueBoolean(const struct NT_Value* value, uint64_t* last_change,
|
||||
|
||||
NT_Bool NT_GetValueDouble(const struct NT_Value* value, uint64_t* last_change,
|
||||
double* v_double) {
|
||||
if (!value || value->type != NT_Type::NT_DOUBLE) return 0;
|
||||
if (!value || value->type != NT_Type::NT_DOUBLE) {
|
||||
return 0;
|
||||
}
|
||||
*last_change = value->last_change;
|
||||
*v_double = value->data.v_double;
|
||||
return 1;
|
||||
@@ -945,7 +1042,9 @@ NT_Bool NT_GetValueDouble(const struct NT_Value* value, uint64_t* last_change,
|
||||
|
||||
char* NT_GetValueString(const struct NT_Value* value, uint64_t* last_change,
|
||||
size_t* str_len) {
|
||||
if (!value || value->type != NT_Type::NT_STRING) return nullptr;
|
||||
if (!value || value->type != NT_Type::NT_STRING) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = value->last_change;
|
||||
*str_len = value->data.v_string.len;
|
||||
char* str =
|
||||
@@ -956,7 +1055,9 @@ char* NT_GetValueString(const struct NT_Value* value, uint64_t* last_change,
|
||||
|
||||
char* NT_GetValueRaw(const struct NT_Value* value, uint64_t* last_change,
|
||||
size_t* raw_len) {
|
||||
if (!value || value->type != NT_Type::NT_RAW) return nullptr;
|
||||
if (!value || value->type != NT_Type::NT_RAW) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = value->last_change;
|
||||
*raw_len = value->data.v_string.len;
|
||||
char* raw =
|
||||
@@ -967,7 +1068,9 @@ char* NT_GetValueRaw(const struct NT_Value* value, uint64_t* last_change,
|
||||
|
||||
NT_Bool* NT_GetValueBooleanArray(const struct NT_Value* value,
|
||||
uint64_t* last_change, size_t* arr_size) {
|
||||
if (!value || value->type != NT_Type::NT_BOOLEAN_ARRAY) return nullptr;
|
||||
if (!value || value->type != NT_Type::NT_BOOLEAN_ARRAY) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = value->last_change;
|
||||
*arr_size = value->data.arr_boolean.size;
|
||||
NT_Bool* arr = static_cast<int*>(
|
||||
@@ -979,7 +1082,9 @@ NT_Bool* NT_GetValueBooleanArray(const struct NT_Value* value,
|
||||
|
||||
double* NT_GetValueDoubleArray(const struct NT_Value* value,
|
||||
uint64_t* last_change, size_t* arr_size) {
|
||||
if (!value || value->type != NT_Type::NT_DOUBLE_ARRAY) return nullptr;
|
||||
if (!value || value->type != NT_Type::NT_DOUBLE_ARRAY) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = value->last_change;
|
||||
*arr_size = value->data.arr_double.size;
|
||||
double* arr = static_cast<double*>(
|
||||
@@ -991,7 +1096,9 @@ double* NT_GetValueDoubleArray(const struct NT_Value* value,
|
||||
|
||||
NT_String* NT_GetValueStringArray(const struct NT_Value* value,
|
||||
uint64_t* last_change, size_t* arr_size) {
|
||||
if (!value || value->type != NT_Type::NT_STRING_ARRAY) return nullptr;
|
||||
if (!value || value->type != NT_Type::NT_STRING_ARRAY) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = value->last_change;
|
||||
*arr_size = value->data.arr_string.size;
|
||||
NT_String* arr = static_cast<NT_String*>(
|
||||
@@ -1051,8 +1158,9 @@ NT_Bool NT_SetDefaultEntryStringArray(NT_Entry entry, uint64_t time,
|
||||
size_t default_size) {
|
||||
std::vector<std::string> vec;
|
||||
vec.reserve(default_size);
|
||||
for (size_t i = 0; i < default_size; ++i)
|
||||
for (size_t i = 0; i < default_size; ++i) {
|
||||
vec.push_back(ConvertFromC(default_value[i]));
|
||||
}
|
||||
|
||||
return nt::SetDefaultEntryValue(entry,
|
||||
Value::MakeStringArray(std::move(vec), time));
|
||||
@@ -1061,7 +1169,9 @@ NT_Bool NT_SetDefaultEntryStringArray(NT_Entry entry, uint64_t time,
|
||||
NT_Bool NT_GetEntryBoolean(NT_Entry entry, uint64_t* last_change,
|
||||
NT_Bool* v_boolean) {
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v || !v->IsBoolean()) return 0;
|
||||
if (!v || !v->IsBoolean()) {
|
||||
return 0;
|
||||
}
|
||||
*v_boolean = v->GetBoolean();
|
||||
*last_change = v->last_change();
|
||||
return 1;
|
||||
@@ -1070,7 +1180,9 @@ NT_Bool NT_GetEntryBoolean(NT_Entry entry, uint64_t* last_change,
|
||||
NT_Bool NT_GetEntryDouble(NT_Entry entry, uint64_t* last_change,
|
||||
double* v_double) {
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v || !v->IsDouble()) return 0;
|
||||
if (!v || !v->IsDouble()) {
|
||||
return 0;
|
||||
}
|
||||
*last_change = v->last_change();
|
||||
*v_double = v->GetDouble();
|
||||
return 1;
|
||||
@@ -1079,7 +1191,9 @@ NT_Bool NT_GetEntryDouble(NT_Entry entry, uint64_t* last_change,
|
||||
char* NT_GetEntryString(NT_Entry entry, uint64_t* last_change,
|
||||
size_t* str_len) {
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v || !v->IsString()) return nullptr;
|
||||
if (!v || !v->IsString()) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = v->last_change();
|
||||
struct NT_String v_string;
|
||||
nt::ConvertToC(v->GetString(), &v_string);
|
||||
@@ -1089,7 +1203,9 @@ char* NT_GetEntryString(NT_Entry entry, uint64_t* last_change,
|
||||
|
||||
char* NT_GetEntryRaw(NT_Entry entry, uint64_t* last_change, size_t* raw_len) {
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v || !v->IsRaw()) return nullptr;
|
||||
if (!v || !v->IsRaw()) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = v->last_change();
|
||||
struct NT_String v_raw;
|
||||
nt::ConvertToC(v->GetRaw(), &v_raw);
|
||||
@@ -1100,7 +1216,9 @@ char* NT_GetEntryRaw(NT_Entry entry, uint64_t* last_change, size_t* raw_len) {
|
||||
NT_Bool* NT_GetEntryBooleanArray(NT_Entry entry, uint64_t* last_change,
|
||||
size_t* arr_size) {
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v || !v->IsBooleanArray()) return nullptr;
|
||||
if (!v || !v->IsBooleanArray()) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = v->last_change();
|
||||
auto vArr = v->GetBooleanArray();
|
||||
NT_Bool* arr =
|
||||
@@ -1113,7 +1231,9 @@ NT_Bool* NT_GetEntryBooleanArray(NT_Entry entry, uint64_t* last_change,
|
||||
double* NT_GetEntryDoubleArray(NT_Entry entry, uint64_t* last_change,
|
||||
size_t* arr_size) {
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v || !v->IsDoubleArray()) return nullptr;
|
||||
if (!v || !v->IsDoubleArray()) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = v->last_change();
|
||||
auto vArr = v->GetDoubleArray();
|
||||
double* arr =
|
||||
@@ -1126,7 +1246,9 @@ double* NT_GetEntryDoubleArray(NT_Entry entry, uint64_t* last_change,
|
||||
NT_String* NT_GetEntryStringArray(NT_Entry entry, uint64_t* last_change,
|
||||
size_t* arr_size) {
|
||||
auto v = nt::GetEntryValue(entry);
|
||||
if (!v || !v->IsStringArray()) return nullptr;
|
||||
if (!v || !v->IsStringArray()) {
|
||||
return nullptr;
|
||||
}
|
||||
*last_change = v->last_change();
|
||||
auto vArr = v->GetStringArray();
|
||||
NT_String* arr = static_cast<NT_String*>(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user