Implement independent instances.

Previously, most of the classes were implemented as singletons so only one
instance was possible.

This change adds an instance handle-based API.  In Java, this API is located
in a different package than the old API (edu.wpi.first.networktables).

Backwards compatibility with ITable and the old NetworkTable API is largely
maintained, but a handful of classes have moved to the new package in Java
(ConnectionInfo and PersistentException), and the old JNI has been completed
replaced.

Also:
- Move SetTeam implementation to Dispatcher.
- Consistently pass time through Java and C++ Value API.
- Rename nt_Value.h to NetworkTableValue.h for consistency with Java.
- Improve documentation
- Make C++ and Java APIs more consistent
- Document RPC functions and support RPC in Java.
- Add polling features for entry and connection listeners and use them to
  move callback threads to Java level.
- Remove thread start and stop hooks (as polling is available).
- Make Notifiers, RpcServer, Dispatcher, and Storage mockable.
- Set NOTIFY_NEW on immediate entry notifications.
- Make GetTable("/") and GetTable("") equivalent.
- Generate local notification for flags update when loading persistent file.

And many unit test updates/changes:
- Use InitGoogleMock instead of InitGoogleTest in test main.
- Move test printers to TestPrinter.h/cpp.
- Provide printers for StringRef, EntryNotifier, and Handle.
- StorageTest: Check notifications.
- Add entry notifier unit tests.
- Storage: Add test for incoming entry assignment.
- Update connection listener tests.
- Add entry listener unit tests.

Fixes #11, #140, #189, #190, #192, #193, #221
This commit is contained in:
Peter Johnson
2017-04-23 10:26:17 -07:00
parent 8125a179fb
commit 5ab20bb27c
118 changed files with 15638 additions and 4640 deletions

View File

@@ -0,0 +1,73 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_ENTRYLISTENERFLAGS_H_
#define NT_ENTRYLISTENERFLAGS_H_
#include "ntcore_c.h"
namespace nt {
namespace EntryListenerFlags {
/**
* Flag values for use with entry listeners.
*
* The flags are a bitmask and must be OR'ed together to indicate the
* combination of events desired to be received.
*
* The constants kNew, kDelete, kUpdate, and kFlags represent different events
* that can occur to entries.
*
* By default, notifications are only generated for remote changes occurring
* after the listener is created. The constants kImmediate and kLocal are
* modifiers that cause notifications to be generated at other times.
*/
enum {
/** Initial listener addition.
* Set this flag to receive immediate notification of entries matching the
* flag criteria (generally only useful when combined with kNew).
*/
kImmediate = NT_NOTIFY_IMMEDIATE,
/** Changed locally.
* Set this flag to receive notification of both local changes and changes
* coming from remote nodes. By default, notifications are only generated
* for remote changes. Must be combined with some combination of kNew,
* kDelete, kUpdate, and kFlags to receive notifications of those respective
* events.
*/
kLocal = NT_NOTIFY_LOCAL,
/** Newly created entry.
* Set this flag to receive a notification when an entry is created.
*/
kNew = NT_NOTIFY_NEW,
/** Entry was deleted.
* Set this flag to receive a notification when an entry is deleted.
*/
kDelete = NT_NOTIFY_DELETE,
/** Entry's value changed.
* Set this flag to receive a notification when an entry's value (or type)
* changes.
*/
kUpdate = NT_NOTIFY_UPDATE,
/** Entry's flags changed.
* Set this flag to receive a notification when an entry's flags value
* changes.
*/
kFlags = NT_NOTIFY_FLAGS
};
} // namespace EntryListenerFlags
} // namespace nt
#endif // NT_ENTRYLISTENERFLAGS_H_

View File

@@ -12,20 +12,35 @@
#include <mutex>
#include <vector>
#include "llvm/StringMap.h"
#include "networktables/NetworkTableEntry.h"
#include "networktables/TableEntryListener.h"
#include "networktables/TableListener.h"
#include "ntcore_c.h"
#include "tables/ITable.h"
namespace nt {
using llvm::ArrayRef;
using llvm::StringRef;
class NetworkTableInstance;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
/**
* A network table that knows its subtable path.
*/
class NetworkTable : public ITable {
class NetworkTable final : public ITable {
private:
struct private_init {};
NT_Inst m_inst;
std::string m_path;
std::mutex m_mutex;
typedef std::pair<ITableListener*, unsigned int> Listener;
mutable std::mutex m_mutex;
mutable llvm::StringMap<NT_Entry> m_entries;
typedef std::pair<ITableListener*, NT_EntryListener> Listener;
std::vector<Listener> m_listeners;
static std::vector<std::string> s_ip_addresses;
@@ -36,31 +51,48 @@ class NetworkTable : public ITable {
static unsigned int s_port;
public:
NetworkTable(llvm::StringRef path, const private_init&);
NetworkTable(NT_Inst inst, StringRef path);
virtual ~NetworkTable();
/**
* Gets the instance for the table.
* @return Instance
*/
NetworkTableInstance GetInstance() const;
/**
* The path separator for sub-tables and keys
*
*/
static const char PATH_SEPARATOR_CHAR;
/**
* @throws IOException
* Initializes network tables
*/
WPI_DEPRECATED(
"use NetworkTableInstance::StartServer() or "
"NetworkTableInstance::StartClient() instead")
static void Initialize();
/**
* Shuts down network tables
*/
WPI_DEPRECATED(
"use NetworkTableInstance::StopServer() or "
"NetworkTableInstance::StopClient() instead")
static void Shutdown();
/**
* set that network tables should be a client
* This must be called before initialize or GetTable
*/
WPI_DEPRECATED("use NetworkTableInstance::StartClient() instead")
static void SetClientMode();
/**
* set that network tables should be a server
* This must be called before initialize or GetTable
*/
WPI_DEPRECATED("use NetworkTableInstance::StartServer() instead")
static void SetServerMode();
/**
@@ -69,30 +101,48 @@ class NetworkTable : public ITable {
* This must be called before initialize or GetTable
* @param team the team number
*/
WPI_DEPRECATED(
"use NetworkTableInstance::SetServerTeam() or "
"NetworkTableInstance::StartClientTeam() instead")
static void SetTeam(int team);
/**
* @param address the adress that network tables will connect to in client
* mode
*/
static void SetIPAddress(llvm::StringRef address);
WPI_DEPRECATED(
"use NetworkTableInstance::SetServer() or "
"NetworkTableInstance::StartClient() instead")
static void SetIPAddress(StringRef address);
/**
* @param addresses the addresses that network tables will connect to in
* client mode (in round robin order)
*/
static void SetIPAddress(llvm::ArrayRef<std::string> addresses);
WPI_DEPRECATED(
"use NetworkTableInstance::SetServer() or "
"NetworkTableInstance::StartClient() instead")
static void SetIPAddress(ArrayRef<std::string> addresses);
/**
* @param port the port number that network tables will connect to in client
* mode or listen to in server mode
* Set the port number that network tables will connect to in client
* mode or listen to in server mode.
* @param port the port number
*/
WPI_DEPRECATED(
"use the appropriate parameters to NetworkTableInstance::SetServer(), "
"NetworkTableInstance::StartClient(), "
"NetworkTableInstance::StartServer(), and "
"NetworkTableInstance::StartDSClient() instead")
static void SetPort(unsigned int port);
/**
* @param enabled whether to enable the connection to the local DS to get
* the robot IP address (defaults to enabled)
* Enable requesting the server address from the Driver Station.
* @param enabled whether to enable the connection to the local DS
*/
WPI_DEPRECATED(
"use NetworkTableInstance::StartDSClient() and "
"NetworkTableInstance::StopDSClient() instead")
static void SetDSClientEnabled(bool enabled);
/**
@@ -100,18 +150,23 @@ class NetworkTable : public ITable {
* @param filename the filename that the network tables server uses for
* automatic loading and saving of persistent values
*/
static void SetPersistentFilename(llvm::StringRef filename);
WPI_DEPRECATED(
"use the appropriate parameter to NetworkTableInstance::StartServer() "
"instead")
static void SetPersistentFilename(StringRef filename);
/**
* Sets the network identity.
* This is provided in the connection info on the remote end.
* @param name identity
*/
static void SetNetworkIdentity(llvm::StringRef name);
WPI_DEPRECATED("use NetworkTableInstance::SetNetworkIdentity() instead")
static void SetNetworkIdentity(StringRef name);
/**
* Deletes ALL keys in ALL subtables. Use with caution!
*/
WPI_DEPRECATED("use NetworkTableInstance::DeleteAllEntries() instead")
static void GlobalDeleteAll();
/**
@@ -120,13 +175,16 @@ class NetworkTable : public ITable {
* This is primarily useful for synchronizing network updates with
* user code.
*/
WPI_DEPRECATED("use NetworkTableInstance::Flush() instead")
static void Flush();
/**
* Set the periodic update rate.
* Sets how frequently updates are sent to other nodes over the network.
*
* @param interval update interval in seconds (range 0.01 to 1.0)
*/
WPI_DEPRECATED("use NetworkTableInstance::SetUpdateRate() instead")
static void SetUpdateRate(double interval);
/**
@@ -135,7 +193,8 @@ class NetworkTable : public ITable {
* @param filename file name
* @return Error (or nullptr).
*/
static const char* SavePersistent(llvm::StringRef filename);
WPI_DEPRECATED("use NetworkTableInstance::SavePersistent() instead")
static const char* SavePersistent(StringRef filename);
/**
* Loads persistent keys from a file. The server does this automatically.
@@ -144,8 +203,9 @@ class NetworkTable : public ITable {
* @param warn callback function called for warnings
* @return Error (or nullptr).
*/
WPI_DEPRECATED("use NetworkTableInstance::LoadPersistent() instead")
static const char* LoadPersistent(
llvm::StringRef filename,
StringRef filename,
std::function<void(size_t line, const char* msg)> warn);
/**
@@ -154,34 +214,103 @@ class NetworkTable : public ITable {
* This will automatically initialize network tables if it has not been
* already.
*
* @param key
* the key name
* @param key the key name
* @return the network table requested
*/
static std::shared_ptr<NetworkTable> GetTable(llvm::StringRef key);
WPI_DEPRECATED(
"use NetworkTableInstance::GetTable() or "
"NetworkTableInstance::GetEntry() instead")
static std::shared_ptr<NetworkTable> GetTable(StringRef key);
/**
* Gets the entry for a subkey.
* @param key the key name
* @return Network table entry.
*/
NetworkTableEntry GetEntry(StringRef key) const;
/**
* Listen to keys only within this table.
* @param listener listener to add
* @param flags EntryListenerFlags bitmask
* @return Listener handle
*/
NT_EntryListener AddEntryListener(TableEntryListener listener,
unsigned int flags) const;
/**
* Listen to a single key.
* @param key the key name
* @param listener listener to add
* @param flags EntryListenerFlags bitmask
* @return Listener handle
*/
NT_EntryListener AddEntryListener(StringRef key, TableEntryListener listener,
unsigned int flags) const;
/**
* Remove an entry listener.
* @param listener listener handle
*/
void RemoveEntryListener(NT_EntryListener listener) const;
/**
* Listen for sub-table creation.
* This calls the listener once for each newly created sub-table.
* It immediately calls the listener for any existing sub-tables.
* @param listener listener to add
* @param localNotify notify local changes as well as remote
* @return Listener handle
*/
NT_EntryListener AddSubTableListener(TableListener listener,
bool localNotify = false) const;
/**
* Remove a sub-table listener.
* @param listener listener handle
*/
void RemoveTableListener(NT_EntryListener listener) const;
WPI_DEPRECATED(
"use AddEntryListener() instead with flags value of NT_NOTIFY_NEW | "
"NT_NOTIFY_UPDATE")
void AddTableListener(ITableListener* listener) override;
WPI_DEPRECATED(
"use AddEntryListener() instead with flags value of NT_NOTIFY_NEW | "
"NT_NOTIFY_UPDATE | NT_NOTIFY_IMMEDIATE")
void AddTableListener(ITableListener* listener,
bool immediateNotify) override;
WPI_DEPRECATED("use AddEntryListener() instead")
void AddTableListenerEx(ITableListener* listener,
unsigned int flags) override;
void AddTableListener(llvm::StringRef key, ITableListener* listener,
WPI_DEPRECATED("use AddEntryListener() instead")
void AddTableListener(StringRef key, ITableListener* listener,
bool immediateNotify) override;
void AddTableListenerEx(llvm::StringRef key, ITableListener* listener,
WPI_DEPRECATED("use AddEntryListener() instead")
void AddTableListenerEx(StringRef key, ITableListener* listener,
unsigned int flags) override;
WPI_DEPRECATED("use AddSubTableListener(TableListener, bool) instead")
void AddSubTableListener(ITableListener* listener) override;
WPI_DEPRECATED("use AddSubTableListener(TableListener, bool) instead")
void AddSubTableListener(ITableListener* listener, bool localNotify) override;
WPI_DEPRECATED("use RemoveTableListener(NT_EntryListener) instead")
void RemoveTableListener(ITableListener* listener) override;
/**
* Returns the table at the specified key. If there is no table at the
* specified key, it will create a new table
*
* @param key
* the key name
* @param key the key name
* @return the networktable to be returned
*/
std::shared_ptr<ITable> GetSubTable(llvm::StringRef key) const override;
std::shared_ptr<NetworkTable> GetSubTable(StringRef key) const override;
/**
* Determines whether the given key is in this table.
@@ -189,7 +318,7 @@ class NetworkTable : public ITable {
* @param key the key to search for
* @return true if the table as a value assigned to the given key
*/
bool ContainsKey(llvm::StringRef key) const override;
bool ContainsKey(StringRef key) const override;
/**
* Determines whether there exists a non-empty subtable for this key
@@ -199,15 +328,17 @@ class NetworkTable : public ITable {
* @return true if there is a subtable with the key which contains at least
* one key/subtable of its own
*/
bool ContainsSubTable(llvm::StringRef key) const override;
bool ContainsSubTable(StringRef key) const override;
/**
* Gets all keys in the table (not including sub-tables).
* @param types bitmask of types; 0 is treated as a "don't care".
* @return keys currently in the table
*/
std::vector<std::string> GetKeys(int types = 0) const override;
/**
* Gets the names of all subtables in the table.
* @return subtables currently in the table
*/
std::vector<std::string> GetSubTables() const override;
@@ -217,7 +348,7 @@ class NetworkTable : public ITable {
*
* @param key the key to make persistent
*/
void SetPersistent(llvm::StringRef key) override;
void SetPersistent(StringRef key) override;
/**
* Stop making a key's value persistent through program restarts.
@@ -225,7 +356,7 @@ class NetworkTable : public ITable {
*
* @param key the key name
*/
void ClearPersistent(llvm::StringRef key) override;
void ClearPersistent(StringRef key) override;
/**
* Returns whether the value is persistent through program restarts.
@@ -233,7 +364,7 @@ class NetworkTable : public ITable {
*
* @param key the key name
*/
bool IsPersistent(llvm::StringRef key) const override;
bool IsPersistent(StringRef key) const override;
/**
* Sets flags on the specified key in this table. The key can
@@ -242,7 +373,7 @@ class NetworkTable : public ITable {
* @param key the key name
* @param flags the flags to set (bitmask)
*/
void SetFlags(llvm::StringRef key, unsigned int flags) override;
void SetFlags(StringRef key, unsigned int flags) override;
/**
* Clears flags on the specified key in this table. The key can
@@ -251,7 +382,7 @@ class NetworkTable : public ITable {
* @param key the key name
* @param flags the flags to clear (bitmask)
*/
void ClearFlags(llvm::StringRef key, unsigned int flags) override;
void ClearFlags(StringRef key, unsigned int flags) override;
/**
* Returns the flags for the specified key.
@@ -259,14 +390,14 @@ class NetworkTable : public ITable {
* @param key the key name
* @return the flags, or 0 if the key is not defined
*/
unsigned int GetFlags(llvm::StringRef key) const override;
unsigned int GetFlags(StringRef key) const override;
/**
* Deletes the specified key in this table.
*
* @param key the key name
*/
void Delete(llvm::StringRef key) override;
void Delete(StringRef key) override;
/**
* Put a number in the table
@@ -275,7 +406,7 @@ class NetworkTable : public ITable {
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*/
bool PutNumber(llvm::StringRef key, double value) override;
bool PutNumber(StringRef key, double value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -283,8 +414,7 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultNumber(llvm::StringRef key,
double defaultValue) override;
bool SetDefaultNumber(StringRef key, double defaultValue) override;
/**
* Gets the number associated with the given name.
@@ -294,8 +424,7 @@ class NetworkTable : public ITable {
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
virtual double GetNumber(llvm::StringRef key,
double defaultValue) const override;
double GetNumber(StringRef key, double defaultValue) const override;
/**
* Put a string in the table
@@ -304,7 +433,7 @@ class NetworkTable : public ITable {
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*/
virtual bool PutString(llvm::StringRef key, llvm::StringRef value) override;
bool PutString(StringRef key, StringRef value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -312,8 +441,7 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultString(llvm::StringRef key,
llvm::StringRef defaultValue) override;
bool SetDefaultString(StringRef key, StringRef defaultValue) override;
/**
* Gets the string associated with the given name. If the key does not
@@ -324,8 +452,7 @@ class NetworkTable : public ITable {
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
virtual std::string GetString(llvm::StringRef key,
llvm::StringRef defaultValue) const override;
std::string GetString(StringRef key, StringRef defaultValue) const override;
/**
* Put a boolean in the table
@@ -334,7 +461,7 @@ class NetworkTable : public ITable {
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*/
virtual bool PutBoolean(llvm::StringRef key, bool value) override;
bool PutBoolean(StringRef key, bool value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -342,8 +469,7 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultBoolean(llvm::StringRef key,
bool defaultValue) override;
bool SetDefaultBoolean(StringRef key, bool defaultValue) override;
/**
* Gets the boolean associated with the given name. If the key does not
@@ -354,8 +480,7 @@ class NetworkTable : public ITable {
* @return the value associated with the given key or the given default value
* if there is no value associated with the key
*/
virtual bool GetBoolean(llvm::StringRef key,
bool defaultValue) const override;
bool GetBoolean(StringRef key, bool defaultValue) const override;
/**
* Put a boolean array in the table
@@ -367,8 +492,7 @@ class NetworkTable : public ITable {
* std::vector<bool> is special-cased in C++. 0 is false, any
* non-zero value is true.
*/
virtual bool PutBooleanArray(llvm::StringRef key,
llvm::ArrayRef<int> value) override;
bool PutBooleanArray(StringRef key, ArrayRef<int> value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -376,8 +500,8 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultBooleanArray(
llvm::StringRef key, llvm::ArrayRef<int> defaultValue) override;
bool SetDefaultBooleanArray(StringRef key,
ArrayRef<int> defaultValue) override;
/**
* Returns the boolean array the key maps to. If the key does not exist or is
@@ -394,8 +518,8 @@ class NetworkTable : public ITable {
* because std::vector<bool> is special-cased in C++. 0 is false, any
* non-zero value is true.
*/
virtual std::vector<int> GetBooleanArray(
llvm::StringRef key, llvm::ArrayRef<int> defaultValue) const override;
std::vector<int> GetBooleanArray(StringRef key,
ArrayRef<int> defaultValue) const override;
/**
* Put a number array in the table
@@ -403,8 +527,7 @@ class NetworkTable : public ITable {
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*/
virtual bool PutNumberArray(llvm::StringRef key,
llvm::ArrayRef<double> value) override;
bool PutNumberArray(StringRef key, ArrayRef<double> value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -412,8 +535,8 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultNumberArray(
llvm::StringRef key, llvm::ArrayRef<double> defaultValue) override;
bool SetDefaultNumberArray(StringRef key,
ArrayRef<double> defaultValue) override;
/**
* Returns the number array the key maps to. If the key does not exist or is
@@ -426,8 +549,8 @@ class NetworkTable : public ITable {
* @note This makes a copy of the array. If the overhead of this is a
* concern, use GetValue() instead.
*/
virtual std::vector<double> GetNumberArray(
llvm::StringRef key, llvm::ArrayRef<double> defaultValue) const override;
std::vector<double> GetNumberArray(
StringRef key, ArrayRef<double> defaultValue) const override;
/**
* Put a string array in the table
@@ -435,8 +558,7 @@ class NetworkTable : public ITable {
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*/
virtual bool PutStringArray(llvm::StringRef key,
llvm::ArrayRef<std::string> value) override;
bool PutStringArray(StringRef key, ArrayRef<std::string> value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -444,8 +566,8 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultStringArray(
llvm::StringRef key, llvm::ArrayRef<std::string> defaultValue) override;
bool SetDefaultStringArray(StringRef key,
ArrayRef<std::string> defaultValue) override;
/**
* Returns the string array the key maps to. If the key does not exist or is
@@ -458,9 +580,8 @@ class NetworkTable : public ITable {
* @note This makes a copy of the array. If the overhead of this is a
* concern, use GetValue() instead.
*/
virtual std::vector<std::string> GetStringArray(
llvm::StringRef key,
llvm::ArrayRef<std::string> defaultValue) const override;
std::vector<std::string> GetStringArray(
StringRef key, ArrayRef<std::string> defaultValue) const override;
/**
* Put a raw value (byte array) in the table
@@ -468,7 +589,7 @@ class NetworkTable : public ITable {
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*/
virtual bool PutRaw(llvm::StringRef key, llvm::StringRef value) override;
bool PutRaw(StringRef key, StringRef value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -476,8 +597,7 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultRaw(llvm::StringRef key,
llvm::StringRef defaultValue) override;
bool SetDefaultRaw(StringRef key, StringRef defaultValue) override;
/**
* Returns the raw value (byte array) the key maps to. If the key does not
@@ -490,8 +610,7 @@ class NetworkTable : public ITable {
* @note This makes a copy of the raw contents. If the overhead of this is a
* concern, use GetValue() instead.
*/
virtual std::string GetRaw(llvm::StringRef key,
llvm::StringRef defaultValue) const override;
std::string GetRaw(StringRef key, StringRef defaultValue) const override;
/**
* Put a value in the table
@@ -500,7 +619,7 @@ class NetworkTable : public ITable {
* @param value the value that will be assigned
* @return False if the table key already exists with a different type
*/
bool PutValue(llvm::StringRef key, std::shared_ptr<Value> value) override;
bool PutValue(StringRef key, std::shared_ptr<Value> value) override;
/**
* Gets the current value in the table, setting it if it does not exist.
@@ -508,8 +627,8 @@ class NetworkTable : public ITable {
* @param defaultValue the default value to set if key doesn't exist.
* @returns False if the table key exists with a different type
*/
virtual bool SetDefaultValue(
llvm::StringRef key, std::shared_ptr<Value> defaultValue) override;
bool SetDefaultValue(StringRef key,
std::shared_ptr<Value> defaultValue) override;
/**
* Gets the value associated with a key as an object
@@ -518,14 +637,19 @@ class NetworkTable : public ITable {
* @return the value associated with the given key, or nullptr if the key
* does not exist
*/
std::shared_ptr<Value> GetValue(llvm::StringRef key) const override;
std::shared_ptr<Value> GetValue(StringRef key) const override;
/**
* Gets the full path of this table.
* Gets the full path of this table. Does not include the trailing "/".
* @return The path (e.g "", "/foo").
*/
llvm::StringRef GetPath() const override;
StringRef GetPath() const override;
};
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
} // namespace nt
// For backwards compatability

View File

@@ -0,0 +1,449 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_ENTRY_H_
#define NT_ENTRY_H_
#include <memory>
#include <string>
#include "llvm/StringRef.h"
#include "networktables/NetworkTableType.h"
#include "networktables/NetworkTableValue.h"
#include "networktables/RpcCall.h"
#include "ntcore_c.h"
#include "ntcore_cpp.h"
namespace nt {
using llvm::ArrayRef;
using llvm::StringRef;
class NetworkTableInstance;
/** NetworkTables Entry */
class NetworkTableEntry final {
public:
/**
* Flag values (as returned by {@link #getFlags()}).
*/
enum Flags { kPersistent = NT_PERSISTENT };
/**
* Construct invalid instance.
*/
NetworkTableEntry();
/**
* Construct from native handle.
* @param handle Native handle
*/
explicit NetworkTableEntry(NT_Entry handle);
/**
* Determines if the native handle is valid.
* @return True if the native handle is valid, false otherwise.
*/
explicit operator bool() const { return m_handle != 0; }
/**
* Gets the native handle for the entry.
* @return Native handle
*/
NT_Entry GetHandle() const;
/**
* Gets the instance for the entry.
* @return Instance
*/
NetworkTableInstance GetInstance() const;
/**
* Determines if the entry currently exists.
* @return True if the entry exists, false otherwise.
*/
bool Exists() const;
/**
* Gets the name of the entry (the key).
* @return the entry's name
*/
std::string GetName() const;
/**
* Gets the type of the entry.
* @return the entry's type
*/
NetworkTableType GetType() const;
/**
* Returns the flags.
* @return the flags (bitmask)
*/
unsigned int GetFlags() const;
/**
* Gets the last time the entry's value was changed.
* @return Entry last change time
*/
unsigned long long GetLastChange() const;
/**
* Gets combined information about the entry.
* @return Entry information
*/
EntryInfo GetInfo() const;
/**
* Gets the entry's value. If the entry does not exist, returns nullptr.
*
* @return the entry's value or nullptr if it does not exist.
*/
std::shared_ptr<Value> GetValue() const;
/**
* Gets the entry's value as a boolean. If the entry does not exist or is of
* different type, it will return the default value.
*
* @param defaultValue the value to be returned if no value is found
* @return the entry's value or the given default value
*/
bool GetBoolean(bool defaultValue) const;
/**
* Gets the entry's value as a double. If the entry does not exist or is of
* different type, it will return the default value.
*
* @param defaultValue the value to be returned if no value is found
* @return the entry's value or the given default value
*/
double GetDouble(double defaultValue) const;
/**
* Gets the entry's value as a string. If the entry does not exist or is of
* different type, it will return the default value.
*
* @param defaultValue the value to be returned if no value is found
* @return the entry's value or the given default value
*/
std::string GetString(StringRef defaultValue) const;
/**
* Gets the entry's value as a raw. If the entry does not exist or is of
* different type, it will return the default value.
*
* @param defaultValue the value to be returned if no value is found
* @return the entry's value or the given default value
*/
std::string GetRaw(StringRef defaultValue) const;
/**
* Gets the entry's value as a boolean array. If the entry does not exist
* or is of different type, it will return the default value.
* @param defaultValue the value to be returned if no value is found
* @return the entry's value or the given default value
*
* @note This makes a copy of the array. If the overhead of this is a
* concern, use GetValue() instead.
*
* @note The returned array is std::vector<int> instead of std::vector<bool>
* because std::vector<bool> is special-cased in C++. 0 is false, any
* non-zero value is true.
*/
std::vector<int> GetBooleanArray(ArrayRef<int> defaultValue) const;
/**
* Gets the entry's value as a double array. If the entry does not exist
* or is of different type, it will return the default value.
* @param defaultValue the value to be returned if no value is found
* @return the entry's value or the given default value
*
* @note This makes a copy of the array. If the overhead of this is a
* concern, use GetValue() instead.
*/
std::vector<double> GetDoubleArray(ArrayRef<double> defaultValue) const;
/**
* Gets the entry's value as a string array. If the entry does not exist
* or is of different type, it will return the default value.
* @param defaultValue the value to be returned if no value is found
* @return the entry's value or the given default value
*
* @note This makes a copy of the array. If the overhead of this is a
* concern, use GetValue() instead.
*/
std::vector<std::string> GetStringArray(
ArrayRef<std::string> defaultValue) const;
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultValue(std::shared_ptr<Value> value);
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultBoolean(bool defaultValue);
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultDouble(double defaultValue);
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultString(StringRef defaultValue);
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultRaw(StringRef defaultValue);
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultBooleanArray(ArrayRef<int> defaultValue);
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultDoubleArray(ArrayRef<double> defaultValue);
/**
* Sets the entry's value if it does not exist.
* @param defaultValue the default value to set
* @return False if the entry exists with a different type
*/
bool SetDefaultStringArray(ArrayRef<std::string> defaultValue);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetValue(std::shared_ptr<Value> value);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetBoolean(bool value);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetDouble(double value);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetString(StringRef value);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetRaw(StringRef value);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetBooleanArray(ArrayRef<int> value);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetDoubleArray(ArrayRef<double> value);
/**
* Sets the entry's value.
* @param value the value to set
* @return False if the entry exists with a different type
*/
bool SetStringArray(ArrayRef<std::string> value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetValue(std::shared_ptr<Value> value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetBoolean(bool value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetDouble(double value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetString(StringRef value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetRaw(StringRef value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetBooleanArray(ArrayRef<int> value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetDoubleArray(ArrayRef<double> value);
/**
* Sets the entry's value. If the value is of different type, the type is
* changed to match the new value.
* @param value the value to set
*/
void ForceSetStringArray(ArrayRef<std::string> value);
/**
* Sets flags.
* @param flags the flags to set (bitmask)
*/
void SetFlags(unsigned int flags);
/**
* Clears flags.
* @param flags the flags to clear (bitmask)
*/
void ClearFlags(unsigned int flags);
/**
* Make value persistent through program restarts.
*/
void SetPersistent();
/**
* Stop making value persistent through program restarts.
*/
void ClearPersistent();
/**
* Returns whether the value is persistent through program restarts.
* @return True if the value is persistent.
*/
bool IsPersistent() const;
/**
* Deletes the entry.
*/
void Delete();
/**
* Create a callback-based RPC entry point. Only valid to use on the server.
* The callback function will be called when the RPC is called.
* This function creates RPC version 0 definitions (raw data in and out).
* @param callback callback function
*/
void CreateRpc(std::function<void(const RpcAnswer& answer)> callback);
/**
* Create a polled RPC entry point. Only valid to use on the server.
* The caller is responsible for calling NetworkTableInstance::PollRpc()
* to poll for servicing incoming RPC calls.
* This function creates RPC version 0 definitions (raw data in and out).
*/
void CreatePolledRpc();
/**
* Call a RPC function. May be used on either the client or server.
* This function is non-blocking. Either RpcCall::GetResult() or
* RpcCall::CancelResult() must be called on the return value to either
* get or ignore the result of the call.
* @param params parameter
* @return RPC call object.
*/
RpcCall CallRpc(StringRef params);
/**
* Add a listener for changes to this entry.
*
* @param callback listener to add
* @param flags NotifyKind bitmask
* @return Listener handle
*/
NT_EntryListener AddListener(
std::function<void(const EntryNotification& event)> callback,
unsigned int flags) const;
/**
* Remove an entry listener.
* @param entry_listener Listener handle to remove
*/
void RemoveListener(NT_EntryListener entry_listener);
/**
* Equality operator. Returns true if both instances refer to the same
* native handle.
*/
bool operator==(const NetworkTableEntry& oth) const {
return m_handle == oth.m_handle;
}
/** Inequality operator. */
bool operator!=(const NetworkTableEntry& oth) const {
return !(*this == oth);
}
protected:
/* Native handle */
NT_Entry m_handle;
};
} // namespace nt
#include "networktables/NetworkTableEntry.inl"
#endif // NT_ENTRY_H_

View File

@@ -0,0 +1,232 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_ENTRY_INL_
#define NT_ENTRY_INL_
namespace nt {
inline NetworkTableEntry::NetworkTableEntry() : m_handle{0} {}
inline NetworkTableEntry::NetworkTableEntry(NT_Entry handle)
: m_handle{handle} {}
inline NT_Entry NetworkTableEntry::GetHandle() const { return m_handle; }
inline bool NetworkTableEntry::Exists() const {
return GetEntryType(m_handle) != NT_UNASSIGNED;
}
inline std::string NetworkTableEntry::GetName() const {
return GetEntryName(m_handle);
}
inline NetworkTableType NetworkTableEntry::GetType() const {
return static_cast<NetworkTableType>(GetEntryType(m_handle));
}
inline unsigned int NetworkTableEntry::GetFlags() const {
return GetEntryFlags(m_handle);
}
inline unsigned long long NetworkTableEntry::GetLastChange() const {
return GetEntryLastChange(m_handle);
}
inline EntryInfo NetworkTableEntry::GetInfo() const {
return GetEntryInfo(m_handle);
}
inline std::shared_ptr<Value> NetworkTableEntry::GetValue() const {
return GetEntryValue(m_handle);
}
inline bool NetworkTableEntry::GetBoolean(bool defaultValue) const {
auto value = GetEntryValue(m_handle);
if (!value || value->type() != NT_BOOLEAN) return defaultValue;
return value->GetBoolean();
}
inline double NetworkTableEntry::GetDouble(double defaultValue) const {
auto value = GetEntryValue(m_handle);
if (!value || value->type() != NT_DOUBLE) return defaultValue;
return value->GetDouble();
}
inline std::string NetworkTableEntry::GetString(StringRef defaultValue) const {
auto value = GetEntryValue(m_handle);
if (!value || value->type() != NT_STRING) return defaultValue;
return value->GetString();
}
inline std::string NetworkTableEntry::GetRaw(StringRef defaultValue) const {
auto value = GetEntryValue(m_handle);
if (!value || value->type() != NT_RAW) return defaultValue;
return value->GetString();
}
inline std::vector<int> NetworkTableEntry::GetBooleanArray(
ArrayRef<int> defaultValue) const {
auto value = GetEntryValue(m_handle);
if (!value || value->type() != NT_BOOLEAN_ARRAY) return defaultValue;
return value->GetBooleanArray();
}
inline std::vector<double> NetworkTableEntry::GetDoubleArray(
ArrayRef<double> defaultValue) const {
auto value = GetEntryValue(m_handle);
if (!value || value->type() != NT_DOUBLE_ARRAY) return defaultValue;
return value->GetDoubleArray();
}
inline std::vector<std::string> NetworkTableEntry::GetStringArray(
ArrayRef<std::string> defaultValue) const {
auto value = GetEntryValue(m_handle);
if (!value || value->type() != NT_STRING_ARRAY) return defaultValue;
return value->GetStringArray();
}
inline bool NetworkTableEntry::SetDefaultValue(std::shared_ptr<Value> value) {
return SetDefaultEntryValue(m_handle, value);
}
inline bool NetworkTableEntry::SetDefaultBoolean(bool defaultValue) {
return SetDefaultEntryValue(m_handle, Value::MakeBoolean(defaultValue));
}
inline bool NetworkTableEntry::SetDefaultDouble(double defaultValue) {
return SetDefaultEntryValue(m_handle, Value::MakeDouble(defaultValue));
}
inline bool NetworkTableEntry::SetDefaultString(StringRef defaultValue) {
return SetDefaultEntryValue(m_handle, Value::MakeString(defaultValue));
}
inline bool NetworkTableEntry::SetDefaultRaw(StringRef defaultValue) {
return SetDefaultEntryValue(m_handle, Value::MakeRaw(defaultValue));
}
inline bool NetworkTableEntry::SetDefaultBooleanArray(
ArrayRef<int> defaultValue) {
return SetDefaultEntryValue(m_handle, Value::MakeBooleanArray(defaultValue));
}
inline bool NetworkTableEntry::SetDefaultDoubleArray(
ArrayRef<double> defaultValue) {
return SetDefaultEntryValue(m_handle, Value::MakeDoubleArray(defaultValue));
}
inline bool NetworkTableEntry::SetDefaultStringArray(
ArrayRef<std::string> defaultValue) {
return SetDefaultEntryValue(m_handle, Value::MakeStringArray(defaultValue));
}
inline bool NetworkTableEntry::SetValue(std::shared_ptr<Value> value) {
return SetEntryValue(m_handle, value);
}
inline bool NetworkTableEntry::SetBoolean(bool value) {
return SetEntryValue(m_handle, Value::MakeBoolean(value));
}
inline bool NetworkTableEntry::SetDouble(double value) {
return SetEntryValue(m_handle, Value::MakeDouble(value));
}
inline bool NetworkTableEntry::SetString(StringRef value) {
return SetEntryValue(m_handle, Value::MakeString(value));
}
inline bool NetworkTableEntry::SetRaw(StringRef value) {
return SetEntryValue(m_handle, Value::MakeRaw(value));
}
inline bool NetworkTableEntry::SetBooleanArray(ArrayRef<int> value) {
return SetEntryValue(m_handle, Value::MakeBooleanArray(value));
}
inline bool NetworkTableEntry::SetDoubleArray(ArrayRef<double> value) {
return SetEntryValue(m_handle, Value::MakeDoubleArray(value));
}
inline bool NetworkTableEntry::SetStringArray(ArrayRef<std::string> value) {
return SetEntryValue(m_handle, Value::MakeStringArray(value));
}
inline void NetworkTableEntry::ForceSetValue(std::shared_ptr<Value> value) {
SetEntryTypeValue(m_handle, value);
}
inline void NetworkTableEntry::ForceSetBoolean(bool value) {
SetEntryTypeValue(m_handle, Value::MakeBoolean(value));
}
inline void NetworkTableEntry::ForceSetDouble(double value) {
SetEntryTypeValue(m_handle, Value::MakeDouble(value));
}
inline void NetworkTableEntry::ForceSetString(StringRef value) {
SetEntryTypeValue(m_handle, Value::MakeString(value));
}
inline void NetworkTableEntry::ForceSetRaw(StringRef value) {
SetEntryTypeValue(m_handle, Value::MakeRaw(value));
}
inline void NetworkTableEntry::ForceSetBooleanArray(ArrayRef<int> value) {
SetEntryTypeValue(m_handle, Value::MakeBooleanArray(value));
}
inline void NetworkTableEntry::ForceSetDoubleArray(ArrayRef<double> value) {
SetEntryTypeValue(m_handle, Value::MakeDoubleArray(value));
}
inline void NetworkTableEntry::ForceSetStringArray(
ArrayRef<std::string> value) {
SetEntryTypeValue(m_handle, Value::MakeStringArray(value));
}
inline void NetworkTableEntry::SetFlags(unsigned int flags) {
SetEntryFlags(m_handle, GetFlags() | flags);
}
inline void NetworkTableEntry::ClearFlags(unsigned int flags) {
SetEntryFlags(m_handle, GetFlags() & ~flags);
}
inline void NetworkTableEntry::SetPersistent() { SetFlags(kPersistent); }
inline void NetworkTableEntry::ClearPersistent() { ClearFlags(kPersistent); }
inline bool NetworkTableEntry::IsPersistent() const {
return (GetFlags() & kPersistent) != 0;
}
inline void NetworkTableEntry::Delete() { DeleteEntry(m_handle); }
inline void NetworkTableEntry::CreateRpc(
std::function<void(const RpcAnswer& answer)> callback) {
::nt::CreateRpc(m_handle, StringRef("\0", 1), callback);
}
inline RpcCall NetworkTableEntry::CallRpc(StringRef params) {
return RpcCall{m_handle, ::nt::CallRpc(m_handle, params)};
}
inline NT_EntryListener NetworkTableEntry::AddListener(
std::function<void(const EntryNotification& event)> callback,
unsigned int flags) const {
return AddEntryListener(m_handle, callback, flags);
}
inline void NetworkTableEntry::RemoveListener(NT_EntryListener entry_listener) {
RemoveEntryListener(entry_listener);
}
} // namespace nt
#endif // NT_ENTRY_INL_

View File

@@ -0,0 +1,521 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_INSTANCE_H_
#define NT_INSTANCE_H_
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include "llvm/ArrayRef.h"
#include "llvm/StringRef.h"
#include "networktables/NetworkTable.h"
#include "networktables/NetworkTableEntry.h"
#include "ntcore_c.h"
#include "ntcore_cpp.h"
#ifndef NT_NOEXCEPT
#ifdef _MSC_VER
#if _MSC_VER >= 1900
#define NT_NOEXCEPT noexcept
#else
#define NT_NOEXCEPT throw()
#endif
#else
#define NT_NOEXCEPT noexcept
#endif
#endif
namespace nt {
using llvm::ArrayRef;
using llvm::StringRef;
/** NetworkTables Instance.
*
* Instances are completely independent from each other. Table operations on
* one instance will not be visible to other instances unless the instances are
* connected via the network. The main limitation on instances is that you
* cannot have two servers on the same network port. The main utility of
* instances is for unit testing, but they can also enable one program to
* connect to two different NetworkTables networks.
*
* The global "default" instance (as returned by GetDefault()) is
* always available, and is intended for the common case when there is only
* a single NetworkTables instance being used in the program. The
* default instance cannot be destroyed.
*
* Additional instances can be created with the Create() function.
* Instances are not reference counted or RAII. Instead, they must be
* explicitly destroyed (with Destroy()).
*/
class NetworkTableInstance final {
public:
/**
* Client/server mode flag values (as returned by GetNetworkMode()).
* This is a bitmask.
*/
enum NetworkMode {
kNetModeNone = NT_NET_MODE_NONE,
kNetModeServer = NT_NET_MODE_SERVER,
kNetModeClient = NT_NET_MODE_CLIENT,
kNetModeStarting = NT_NET_MODE_STARTING,
kNetModeFailure = NT_NET_MODE_FAILURE
};
/**
* Logging levels (as used by SetLogger()).
*/
enum LogLevel {
kLogCritical = NT_LOG_CRITICAL,
kLogError = NT_LOG_ERROR,
kLogWarning = NT_LOG_WARNING,
kLogInfo = NT_LOG_INFO,
kLogDebug = NT_LOG_DEBUG,
kLogDebug1 = NT_LOG_DEBUG1,
kLogDebug2 = NT_LOG_DEBUG2,
kLogDebug3 = NT_LOG_DEBUG3,
kLogDebug4 = NT_LOG_DEBUG4
};
/**
* The default port that network tables operates on.
*/
enum { kDefaultPort = NT_DEFAULT_PORT };
/**
* Construct invalid instance.
*/
NetworkTableInstance() NT_NOEXCEPT;
/**
* Construct from native handle.
* @param handle Native handle
*/
explicit NetworkTableInstance(NT_Inst inst) NT_NOEXCEPT;
/**
* Determines if the native handle is valid.
* @return True if the native handle is valid, false otherwise.
*/
explicit operator bool() const { return m_handle != 0; }
/**
* Get global default instance.
* @return Global default instance
*/
static NetworkTableInstance GetDefault();
/**
* Create an instance.
* @return Newly created instance
*/
static NetworkTableInstance Create();
/**
* Destroys an instance (note: this has global effect).
* @param inst Instance
*/
static void Destroy(NetworkTableInstance inst);
/**
* Gets the native handle for the entry.
* @return Native handle
*/
NT_Inst GetHandle() const;
/**
* Gets the entry for a key.
* @param name Key
* @return Network table entry.
*/
NetworkTableEntry GetEntry(StringRef name);
/**
* Get entries starting with the given prefix.
* The results are optionally filtered by string prefix and entry type to
* only return a subset of all entries.
*
* @param prefix entry name required prefix; only entries whose name
* starts with this string are returned
* @param types bitmask of types; 0 is treated as a "don't care"
* @return Array of entries.
*/
std::vector<NetworkTableEntry> GetEntries(StringRef prefix,
unsigned int types);
/**
* Get information about entries starting with the given prefix.
* The results are optionally filtered by string prefix and entry type to
* only return a subset of all entries.
*
* @param prefix entry name required prefix; only entries whose name
* starts with this string are returned
* @param types bitmask of types; 0 is treated as a "don't care"
* @return Array of entry information.
*/
std::vector<EntryInfo> GetEntryInfo(StringRef prefix,
unsigned int types) const;
/**
* Gets the table with the specified key.
*
* @param key the key name
* @return The network table
*/
std::shared_ptr<NetworkTable> GetTable(StringRef key) const;
/**
* Deletes ALL keys in ALL subtables (except persistent values).
* Use with caution!
*/
void DeleteAllEntries();
/**
* @defgroup EntryListenerFunctions Entry Listener Functions
* @{
*/
/**
* Add a listener for all entries starting with a certain prefix.
*
* @param prefix UTF-8 string prefix
* @param callback listener to add
* @param flags EntryListenerFlags bitmask
* @return Listener handle
*/
NT_EntryListener AddEntryListener(
StringRef prefix,
std::function<void(const EntryNotification& event)> callback,
unsigned int flags) const;
/**
* Remove an entry listener.
* @param entry_listener Listener handle to remove
*/
static void RemoveEntryListener(NT_EntryListener entry_listener);
/**
* Wait for the entry listener queue to be empty. This is primarily useful
* for deterministic testing. This blocks until either the entry listener
* queue is empty (e.g. there are no more events that need to be passed along
* to callbacks or poll queues) or the timeout expires.
* @param timeout timeout, in seconds. Set to 0 for non-blocking behavior,
* or a negative value to block indefinitely
* @return False if timed out, otherwise true.
*/
bool WaitForEntryListenerQueue(double timeout);
/** @} */
/**
* @defgroup ConnectionListenerFunctions Connection Listener Functions
* @{
*/
/**
* Add a connection listener.
*
* @param callback listener to add
* @param immediate_notify notify listener of all existing connections
* @return Listener handle
*/
NT_ConnectionListener AddConnectionListener(
std::function<void(const ConnectionNotification& event)> callback,
bool immediate_notify) const;
/**
* Remove a connection listener.
* @param conn_listener Listener handle to remove
*/
static void RemoveConnectionListener(NT_ConnectionListener conn_listener);
/**
* Wait for the connection listener queue to be empty. This is primarily useful
* for deterministic testing. This blocks until either the connection listener
* queue is empty (e.g. there are no more events that need to be passed along
* to callbacks or poll queues) or the timeout expires.
* @param timeout timeout, in seconds. Set to 0 for non-blocking behavior,
* or a negative value to block indefinitely
* @return False if timed out, otherwise true.
*/
bool WaitForConnectionListenerQueue(double timeout);
/** @} */
/**
* @defgroup RpcFunctions Remote Procedure Call Functions
* @{
*/
/**
* Wait for the incoming RPC call queue to be empty. This is primarily useful
* for deterministic testing. This blocks until either the RPC call
* queue is empty (e.g. there are no more events that need to be passed along
* to callbacks or poll queues) or the timeout expires.
* @param timeout timeout, in seconds. Set to 0 for non-blocking behavior,
* or a negative value to block indefinitely
* @return False if timed out, otherwise true.
*/
bool WaitForRpcCallQueue(double timeout);
/** @} */
/**
* @defgroup NetworkFunctions Client/Server Functions
* @{
*/
/**
* Set the network identity of this node.
* This is the name used during the initial connection handshake, and is
* visible through ConnectionInfo on the remote node.
* @param name identity to advertise
*/
void SetNetworkIdentity(StringRef name);
/**
* Get the current network mode.
* @return Bitmask of NetworkMode.
*/
unsigned int GetNetworkMode() const;
/**
* Starts a server using the specified filename, listening address, and port.
*
* @param persist_filename the name of the persist file to use (UTF-8 string,
* null terminated)
* @param listen_address the address to listen on, or null to listen on any
* address (UTF-8 string, null terminated)
* @param port port to communicate over
*/
void StartServer(StringRef persist_filename = "networktables.ini",
const char* listen_address = "",
unsigned int port = kDefaultPort);
/**
* Stops the server if it is running.
*/
void StopServer();
/**
* Starts a client. Use SetServer to set the server name and port.
*/
void StartClient();
/**
* Starts a client using the specified server and port
*
* @param server_name server name (UTF-8 string, null terminated)
* @param port port to communicate over
*/
void StartClient(const char* server_name, unsigned int port = kDefaultPort);
/**
* Starts a client using the specified (server, port) combinations. The
* client will attempt to connect to each server in round robin fashion.
*
* @param servers array of server name and port pairs
*/
void StartClient(ArrayRef<std::pair<StringRef, unsigned int>> servers);
/**
* Starts a client using the specified servers and port. The
* client will attempt to connect to each server in round robin fashion.
*
* @param servers array of server names
* @param port port to communicate over
*/
void StartClient(ArrayRef<StringRef> servers,
unsigned int port = kDefaultPort);
/**
* Starts a client using commonly known robot addresses for the specified
* team.
*
* @param team team number
* @param port port to communicate over
*/
void StartClientTeam(unsigned int team, unsigned int port = kDefaultPort);
/**
* Stops the client if it is running.
*/
void StopClient();
/**
* Sets server address and port for client (without restarting client).
*
* @param server_name server name (UTF-8 string, null terminated)
* @param port port to communicate over
*/
void SetServer(const char* server_name, unsigned int port = kDefaultPort);
/**
* Sets server addresses and ports for client (without restarting client).
* The client will attempt to connect to each server in round robin fashion.
*
* @param servers array of server name and port pairs
*/
void SetServer(ArrayRef<std::pair<StringRef, unsigned int>> servers);
/**
* Sets server addresses and port for client (without restarting client).
* The client will attempt to connect to each server in round robin fashion.
*
* @param servers array of server names
* @param port port to communicate over
*/
void SetServer(ArrayRef<StringRef> servers, unsigned int port = kDefaultPort);
/**
* Sets server addresses and port for client (without restarting client).
* Connects using commonly known robot addresses for the specified team.
*
* @param team team number
* @param port port to communicate over
*/
void SetServerTeam(unsigned int team, unsigned int port = kDefaultPort);
/**
* Starts requesting server address from Driver Station.
* This connects to the Driver Station running on localhost to obtain the
* server IP address.
*
* @param port server port to use in combination with IP from DS
*/
void StartDSClient(unsigned int port = kDefaultPort);
/**
* Stops requesting server address from Driver Station.
*/
void StopDSClient();
/**
* Set the periodic update rate.
* Sets how frequently updates are sent to other nodes over the network.
*
* @param interval update interval in seconds (range 0.01 to 1.0)
*/
void SetUpdateRate(double interval);
/**
* Flushes all updated values immediately to the network.
* @note This is rate-limited to protect the network from flooding.
* This is primarily useful for synchronizing network updates with
* user code.
*/
void Flush() const;
/**
* Get information on the currently established network connections.
* If operating as a client, this will return either zero or one values.
* @return array of connection information
*/
std::vector<ConnectionInfo> GetConnections() const;
/**
* Return whether or not the instance is connected to another node.
* @return True if connected.
*/
bool IsConnected() const;
/** @} */
/**
* @defgroup PersistentFunctions Persistent Functions
* @{
*/
/**
* Save persistent values to a file. The server automatically does this,
* but this function provides a way to save persistent values in the same
* format to a file on either a client or a server.
* @param filename filename
* @return error string, or nullptr if successful
*/
const char* SavePersistent(StringRef filename) const;
/**
* Load persistent values from a file. The server automatically does this
* at startup, but this function provides a way to restore persistent values
* in the same format from a file at any time on either a client or a server.
* @param filename filename
* @param warn callback function for warnings
* @return error string, or nullptr if successful
*/
const char* LoadPersistent(
StringRef filename,
std::function<void(size_t line, const char* msg)> warn);
/** @} */
/**
* @defgroup LoggerFunctions Logger Functions
* @{
*/
/**
* Add logger callback function. By default, log messages are sent to stderr;
* this function sends log messages with the specified levels to the provided
* callback function instead. The callback function will only be called for
* log messages with level greater than or equal to minLevel and less than or
* equal to maxLevel; messages outside this range will be silently ignored.
*
* @param func log callback function
* @param minLevel minimum log level
* @param maxLevel maximum log level
* @return Logger handle
*/
NT_Logger AddLogger(std::function<void(const LogMessage& msg)> func,
unsigned int min_level, unsigned int max_level);
/**
* Remove a logger.
* @param logger Logger handle to remove
*/
static void RemoveLogger(NT_Logger logger);
/**
* Wait for the incoming log event queue to be empty. This is primarily useful
* for deterministic testing. This blocks until either the log event
* queue is empty (e.g. there are no more events that need to be passed along
* to callbacks or poll queues) or the timeout expires.
* @param timeout timeout, in seconds. Set to 0 for non-blocking behavior,
* or a negative value to block indefinitely
* @return False if timed out, otherwise true.
*/
bool WaitForLoggerQueue(double timeout);
/** @} */
/**
* Equality operator. Returns true if both instances refer to the same
* native handle.
*/
bool operator==(const NetworkTableInstance& other) const {
return m_handle == other.m_handle;
}
/** Inequality operator. */
bool operator!=(const NetworkTableInstance& other) const {
return !(*this == other);
}
private:
/* Native handle */
NT_Inst m_handle;
};
} // namespace nt
#include "networktables/NetworkTableInstance.inl"
#endif // NT_INSTANCE_H_

View File

@@ -0,0 +1,176 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_INSTANCE_INL_
#define NT_INSTANCE_INL_
namespace nt {
inline NetworkTableInstance::NetworkTableInstance() NT_NOEXCEPT : m_handle{0} {}
inline NetworkTableInstance::NetworkTableInstance(NT_Inst handle) NT_NOEXCEPT
: m_handle{handle} {}
inline NetworkTableInstance NetworkTableInstance::GetDefault() {
return NetworkTableInstance{GetDefaultInstance()};
}
inline NetworkTableInstance NetworkTableInstance::Create() {
return NetworkTableInstance{CreateInstance()};
}
inline void NetworkTableInstance::Destroy(NetworkTableInstance inst) {
if (inst.m_handle != 0) DestroyInstance(inst.m_handle);
}
inline NT_Inst NetworkTableInstance::GetHandle() const { return m_handle; }
inline NetworkTableEntry NetworkTableInstance::GetEntry(StringRef name) {
return NetworkTableEntry{::nt::GetEntry(m_handle, name)};
}
inline std::vector<NetworkTableEntry> NetworkTableInstance::GetEntries(
StringRef prefix, unsigned int types) {
std::vector<NetworkTableEntry> entries;
for (auto entry : ::nt::GetEntries(m_handle, prefix, types))
entries.emplace_back(entry);
return entries;
}
inline std::vector<EntryInfo> NetworkTableInstance::GetEntryInfo(
StringRef prefix, unsigned int types) const {
return ::nt::GetEntryInfo(m_handle, prefix, types);
}
inline void NetworkTableInstance::DeleteAllEntries() {
::nt::DeleteAllEntries(m_handle);
}
inline void NetworkTableInstance::RemoveEntryListener(
NT_EntryListener entry_listener) {
::nt::RemoveEntryListener(entry_listener);
}
inline bool NetworkTableInstance::WaitForEntryListenerQueue(double timeout) {
return ::nt::WaitForEntryListenerQueue(m_handle, timeout);
}
inline void NetworkTableInstance::RemoveConnectionListener(
NT_ConnectionListener conn_listener) {
::nt::RemoveConnectionListener(conn_listener);
}
inline bool NetworkTableInstance::WaitForConnectionListenerQueue(
double timeout) {
return ::nt::WaitForConnectionListenerQueue(m_handle, timeout);
}
inline bool NetworkTableInstance::WaitForRpcCallQueue(double timeout) {
return ::nt::WaitForRpcCallQueue(m_handle, timeout);
}
inline void NetworkTableInstance::SetNetworkIdentity(StringRef name) {
::nt::SetNetworkIdentity(m_handle, name);
}
inline unsigned int NetworkTableInstance::GetNetworkMode() const {
return ::nt::GetNetworkMode(m_handle);
}
inline void NetworkTableInstance::StartServer(StringRef persist_filename,
const char* listen_address,
unsigned int port) {
::nt::StartServer(m_handle, persist_filename, listen_address, port);
}
inline void NetworkTableInstance::StopServer() { ::nt::StopServer(m_handle); }
inline void NetworkTableInstance::StartClient() { ::nt::StartClient(m_handle); }
inline void NetworkTableInstance::StartClient(const char* server_name,
unsigned int port) {
::nt::StartClient(m_handle, server_name, port);
}
inline void NetworkTableInstance::StartClient(
ArrayRef<std::pair<StringRef, unsigned int>> servers) {
::nt::StartClient(m_handle, servers);
}
inline void NetworkTableInstance::StartClientTeam(unsigned int team,
unsigned int port) {
::nt::StartClientTeam(m_handle, team, port);
}
inline void NetworkTableInstance::StopClient() { ::nt::StopClient(m_handle); }
inline void NetworkTableInstance::SetServer(const char* server_name,
unsigned int port) {
::nt::SetServer(m_handle, server_name, port);
}
inline void NetworkTableInstance::SetServer(
ArrayRef<std::pair<StringRef, unsigned int>> servers) {
::nt::SetServer(m_handle, servers);
}
inline void NetworkTableInstance::SetServerTeam(unsigned int team,
unsigned int port) {
::nt::SetServerTeam(m_handle, team, port);
}
inline void NetworkTableInstance::StartDSClient(unsigned int port) {
::nt::StartDSClient(m_handle, port);
}
inline void NetworkTableInstance::StopDSClient() {
::nt::StopDSClient(m_handle);
}
inline void NetworkTableInstance::SetUpdateRate(double interval) {
::nt::SetUpdateRate(m_handle, interval);
}
inline void NetworkTableInstance::Flush() const { ::nt::Flush(m_handle); }
inline std::vector<ConnectionInfo> NetworkTableInstance::GetConnections()
const {
return ::nt::GetConnections(m_handle);
}
inline bool NetworkTableInstance::IsConnected() const {
return ::nt::IsConnected(m_handle);
}
inline const char* NetworkTableInstance::SavePersistent(
StringRef filename) const {
return ::nt::SavePersistent(m_handle, filename);
}
inline const char* NetworkTableInstance::LoadPersistent(
StringRef filename,
std::function<void(size_t line, const char* msg)> warn) {
return ::nt::LoadPersistent(m_handle, filename, warn);
}
inline NT_Logger NetworkTableInstance::AddLogger(
std::function<void(const LogMessage& msg)> func, unsigned int min_level,
unsigned int max_level) {
return ::nt::AddLogger(m_handle, func, min_level, max_level);
}
inline void NetworkTableInstance::RemoveLogger(NT_Logger logger) {
::nt::RemoveLogger(logger);
}
inline bool NetworkTableInstance::WaitForLoggerQueue(double timeout) {
return ::nt::WaitForLoggerQueue(m_handle, timeout);
}
} // namespace nt
#endif // NT_INSTANCE_INL_

View File

@@ -0,0 +1,29 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_TYPE_H_
#define NT_TYPE_H_
#include "ntcore_c.h"
namespace nt {
enum class NetworkTableType {
kUnassigned = NT_UNASSIGNED,
kBoolean = NT_BOOLEAN,
kDouble = NT_DOUBLE,
kString = NT_STRING,
kRaw = NT_RAW,
kBooleanArray = NT_BOOLEAN_ARRAY,
kDoubleArray = NT_DOUBLE_ARRAY,
kStringArray = NT_STRING_ARRAY,
kRpc = NT_RPC
};
} // namespace nt
#endif // NT_TYPE_H_

View File

@@ -0,0 +1,404 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_VALUE_H_
#define NT_VALUE_H_
#include <cassert>
#include <memory>
#include <string>
#include <type_traits>
#include <vector>
#include "llvm/ArrayRef.h"
#include "llvm/StringRef.h"
#include "ntcore_c.h"
namespace nt {
using llvm::ArrayRef;
using llvm::StringRef;
/**
* A network table entry value.
*/
class Value final {
struct private_init {};
public:
Value();
Value(NT_Type type, unsigned long long time, const private_init&);
~Value();
/**
* Get the data type.
* @return The type.
*/
NT_Type type() const { return m_val.type; }
/**
* Get the data value stored.
* @return The type.
*/
const NT_Value& value() const { return m_val; }
/**
* Get the creation time of the value.
* @return The time, in the units returned by nt::Now().
*/
unsigned long long last_change() const { return m_val.last_change; }
/**
* Get the creation time of the value.
* @return The time, in the units returned by nt::Now().
*/
unsigned long long time() const { return m_val.last_change; }
/**
* @defgroup TypeCheckers Type Checkers
* @{
*/
/**
* Determine if entry value contains a value or is unassigned.
* @return True if the entry value contains a value.
*/
bool IsValid() const { return m_val.type != NT_UNASSIGNED; }
/**
* Determine if entry value contains a boolean.
* @return True if the entry value is of boolean type.
*/
bool IsBoolean() const { return m_val.type == NT_BOOLEAN; }
/**
* Determine if entry value contains a double.
* @return True if the entry value is of double type.
*/
bool IsDouble() const { return m_val.type == NT_DOUBLE; }
/**
* Determine if entry value contains a string.
* @return True if the entry value is of string type.
*/
bool IsString() const { return m_val.type == NT_STRING; }
/**
* Determine if entry value contains a raw.
* @return True if the entry value is of raw type.
*/
bool IsRaw() const { return m_val.type == NT_RAW; }
/**
* Determine if entry value contains a rpc definition.
* @return True if the entry value is of rpc definition type.
*/
bool IsRpc() const { return m_val.type == NT_RPC; }
/**
* Determine if entry value contains a boolean array.
* @return True if the entry value is of boolean array type.
*/
bool IsBooleanArray() const { return m_val.type == NT_BOOLEAN_ARRAY; }
/**
* Determine if entry value contains a double array.
* @return True if the entry value is of double array type.
*/
bool IsDoubleArray() const { return m_val.type == NT_DOUBLE_ARRAY; }
/**
* Determine if entry value contains a string array.
* @return True if the entry value is of string array type.
*/
bool IsStringArray() const { return m_val.type == NT_STRING_ARRAY; }
/** @} */
/**
* @defgroup TypeSafeGetters Type-Safe Getters
* @{
*/
/**
* Get the entry's boolean value.
* @return The boolean value.
*/
bool GetBoolean() const {
assert(m_val.type == NT_BOOLEAN);
return m_val.data.v_boolean != 0;
}
/**
* Get the entry's double value.
* @return The double value.
*/
double GetDouble() const {
assert(m_val.type == NT_DOUBLE);
return m_val.data.v_double;
}
/**
* Get the entry's string value.
* @return The string value.
*/
StringRef GetString() const {
assert(m_val.type == NT_STRING);
return m_string;
}
/**
* Get the entry's raw value.
* @return The raw value.
*/
StringRef GetRaw() const {
assert(m_val.type == NT_RAW);
return m_string;
}
/**
* Get the entry's rpc definition value.
* @return The rpc definition value.
*/
StringRef GetRpc() const {
assert(m_val.type == NT_RPC);
return m_string;
}
/**
* Get the entry's boolean array value.
* @return The boolean array value.
*/
ArrayRef<int> GetBooleanArray() const {
assert(m_val.type == NT_BOOLEAN_ARRAY);
return ArrayRef<int>(m_val.data.arr_boolean.arr,
m_val.data.arr_boolean.size);
}
/**
* Get the entry's double array value.
* @return The double array value.
*/
ArrayRef<double> GetDoubleArray() const {
assert(m_val.type == NT_DOUBLE_ARRAY);
return ArrayRef<double>(m_val.data.arr_double.arr,
m_val.data.arr_double.size);
}
/**
* Get the entry's string array value.
* @return The string array value.
*/
ArrayRef<std::string> GetStringArray() const {
assert(m_val.type == NT_STRING_ARRAY);
return m_string_array;
}
/** @} */
/**
* @defgroup Factories Factory functions
* @{
*/
/**
* Creates a boolean entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeBoolean(bool value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_BOOLEAN, time, private_init());
val->m_val.data.v_boolean = value;
return val;
}
/**
* Creates a double entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeDouble(double value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_DOUBLE, time, private_init());
val->m_val.data.v_double = value;
return val;
}
/**
* Creates a string entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeString(StringRef value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_STRING, time, private_init());
val->m_string = value;
val->m_val.data.v_string.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_string.len = val->m_string.size();
return val;
}
/**
* Creates a string entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
#ifdef _MSC_VER
template <typename T,
typename = std::enable_if_t<std::is_same<T, std::string>>>
#else
template <typename T,
typename std::enable_if<std::is_same<T, std::string>::value>::type>
#endif
static std::shared_ptr<Value> MakeString(T&& value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_STRING, time, private_init());
val->m_string = std::move(value);
val->m_val.data.v_string.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_string.len = val->m_string.size();
return val;
}
/**
* Creates a raw entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeRaw(StringRef value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_RAW, time, private_init());
val->m_string = value;
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
/**
* Creates a raw entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
#ifdef _MSC_VER
template <typename T,
typename = std::enable_if_t<std::is_same<T, std::string>>>
#else
template <typename T,
typename std::enable_if<std::is_same<T, std::string>::value>::type>
#endif
static std::shared_ptr<Value> MakeRaw(T&& value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_RAW, time, private_init());
val->m_string = std::move(value);
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
/**
* Creates a rpc entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeRpc(StringRef value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_RPC, time, private_init());
val->m_string = value;
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
/**
* Creates a rpc entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
template <typename T>
static std::shared_ptr<Value> MakeRpc(T&& value,
unsigned long long time = 0) {
auto val = std::make_shared<Value>(NT_RPC, time, private_init());
val->m_string = std::move(value);
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
/**
* Creates a boolean array entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeBooleanArray(ArrayRef<int> value,
unsigned long long time = 0);
/**
* Creates a double array entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeDoubleArray(ArrayRef<double> value,
unsigned long long time = 0);
/**
* Creates a string array entry value.
* @param value the value
* @param time if nonzero, the creation time to use (instead of the current
* time)
* @return The entry value
*/
static std::shared_ptr<Value> MakeStringArray(ArrayRef<std::string> value,
unsigned long long time = 0);
// Note: This function moves the values out of the vector.
static std::shared_ptr<Value> MakeStringArray(
std::vector<std::string>&& value, unsigned long long time = 0);
/** @} */
Value(const Value&) = delete;
Value& operator=(const Value&) = delete;
friend bool operator==(const Value& lhs, const Value& rhs);
private:
NT_Value m_val;
std::string m_string;
std::vector<std::string> m_string_array;
};
bool operator==(const Value& lhs, const Value& rhs);
inline bool operator!=(const Value& lhs, const Value& rhs) {
return !(lhs == rhs);
}
/** NetworkTable Value alias for similarity with Java. */
typedef Value NetworkTableValue;
} // namespace nt
#endif // NT_VALUE_H_

View File

@@ -0,0 +1,101 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_RPCCALL_H_
#define NT_RPCCALL_H_
#include <string>
#include <utility>
#include "ntcore_c.h"
namespace nt {
class NetworkTableEntry;
/** NetworkTables Remote Procedure Call */
class RpcCall final {
public:
/**
* Construct invalid instance.
*/
RpcCall() : m_entry(0), m_call(0) {}
/**
* Construct from native handles.
* @param entry Entry handle
* @param call Call handle
*/
RpcCall(NT_Entry entry, NT_RpcCall call)
: m_entry(entry), m_call(call) {}
RpcCall(RpcCall&& other);
RpcCall(const RpcCall&) = delete;
RpcCall& operator=(const RpcCall&) = delete;
/**
* Destructor. Cancels the result if no other action taken.
*/
~RpcCall();
/**
* Determines if the native handle is valid.
* @return True if the native handle is valid, false otherwise.
*/
explicit operator bool() const { return m_call != 0; }
/**
* Get the RPC entry.
* @return NetworkTableEntry for the RPC.
*/
NetworkTableEntry GetEntry() const;
/**
* Get the call native handle.
* @return Native handle.
*/
NT_RpcCall GetCall() const { return m_call; }
/**
* Get the result (return value). This function blocks until
* the result is received.
* @param result received result (output)
* @return False on error, true otherwise.
*/
bool GetResult(std::string* result);
/**
* Get the result (return value). This function blocks until
* the result is received or it times out.
* @param result received result (output)
* @param timeout timeout, in seconds
* @param timed_out true if the timeout period elapsed (output)
* @return False on error or timeout, true otherwise.
*/
bool GetResult(std::string* result, double timeout, bool* timed_out);
/**
* Ignore the result. This function is non-blocking.
*/
void CancelResult();
friend void swap(RpcCall& first, RpcCall& second) {
using std::swap;
swap(first.m_entry, second.m_entry);
swap(first.m_call, second.m_call);
}
private:
NT_Entry m_entry;
NT_RpcCall m_call;
};
} // namespace nt
#include "networktables/RpcCall.inl"
#endif // NT_RPCCALL_H_

View File

@@ -0,0 +1,48 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_RPCCALL_INL_
#define NT_RPCCALL_INL_
#include "ntcore_cpp.h"
namespace nt {
inline RpcCall::RpcCall(RpcCall&& other) : RpcCall() {
swap(*this, other);
}
inline RpcCall::~RpcCall() {
// automatically cancel result if user didn't request it
if (m_call != 0) CancelResult();
}
inline bool RpcCall::GetResult(std::string* result) {
if (GetRpcResult(m_entry, m_call, result)) {
m_call = 0;
return true;
}
return false;
}
inline bool RpcCall::GetResult(std::string* result, double timeout,
bool* timed_out) {
if (GetRpcResult(m_entry, m_call, result, timeout, timed_out)) {
m_call = 0;
return true;
}
return false;
}
inline void RpcCall::CancelResult() {
CancelRpcResult(m_entry, m_call);
m_call = 0;
}
} // namespace nt
#endif // NT_RPCCALL_INL_

View File

@@ -0,0 +1,43 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_TABLEENTRYLISTENER_H_
#define NT_TABLEENTRYLISTENER_H_
#include <functional>
#include <memory>
#include "llvm/StringRef.h"
namespace nt {
class NetworkTable;
class NetworkTableEntry;
class Value;
using llvm::StringRef;
/**
* A listener that listens to changes in values in a NetworkTable.
*
* Called when a key-value pair is changed in a NetworkTable.
*
* @param table the table the key-value pair exists in
* @param key the key associated with the value that changed
* @param entry the entry associated with the value that changed
* @param value the new value
* @param flags update flags; for example, EntryListenerFlags.kNew if the key
* did not previously exist
*/
typedef std::function<void(NetworkTable* table, StringRef name,
NetworkTableEntry entry,
std::shared_ptr<Value> value, int flags)>
TableEntryListener;
} // namespace nt
#endif // NT_TABLEENTRYLISTENER_H_

View File

@@ -0,0 +1,37 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2017. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_TABLELISTENER_H_
#define NT_TABLELISTENER_H_
#include <functional>
#include <memory>
#include "llvm/StringRef.h"
namespace nt {
class NetworkTable;
using llvm::StringRef;
/**
* A listener that listens to new sub-tables in a NetworkTable.
*
* Called when a new table is created.
*
* @param parent the parent of the table
* @param name the name of the new table
* @param table the new table
*/
typedef std::function<void(NetworkTable* parent, StringRef name,
NetworkTable* table)>
TableListener;
} // namespace nt
#endif // NT_TABLELISTENER_H_

View File

@@ -1,183 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_VALUE_H_
#define NT_VALUE_H_
#include <cassert>
#include <memory>
#include <string>
#include <type_traits>
#include <vector>
#include "llvm/ArrayRef.h"
#include "llvm/StringRef.h"
#include "ntcore_c.h"
namespace nt {
using llvm::ArrayRef;
using llvm::StringRef;
/** NetworkTables Entry Value */
class Value {
struct private_init {};
public:
Value();
Value(NT_Type type, const private_init&);
~Value();
NT_Type type() const { return m_val.type; }
const NT_Value& value() const { return m_val; }
unsigned long long last_change() const { return m_val.last_change; }
/*
* Type Checkers
*/
bool IsBoolean() const { return m_val.type == NT_BOOLEAN; }
bool IsDouble() const { return m_val.type == NT_DOUBLE; }
bool IsString() const { return m_val.type == NT_STRING; }
bool IsRaw() const { return m_val.type == NT_RAW; }
bool IsRpc() const { return m_val.type == NT_RPC; }
bool IsBooleanArray() const { return m_val.type == NT_BOOLEAN_ARRAY; }
bool IsDoubleArray() const { return m_val.type == NT_DOUBLE_ARRAY; }
bool IsStringArray() const { return m_val.type == NT_STRING_ARRAY; }
/*
* Type-Safe Getters
*/
bool GetBoolean() const {
assert(m_val.type == NT_BOOLEAN);
return m_val.data.v_boolean != 0;
}
double GetDouble() const {
assert(m_val.type == NT_DOUBLE);
return m_val.data.v_double;
}
StringRef GetString() const {
assert(m_val.type == NT_STRING);
return m_string;
}
StringRef GetRaw() const {
assert(m_val.type == NT_RAW);
return m_string;
}
StringRef GetRpc() const {
assert(m_val.type == NT_RPC);
return m_string;
}
ArrayRef<int> GetBooleanArray() const {
assert(m_val.type == NT_BOOLEAN_ARRAY);
return ArrayRef<int>(m_val.data.arr_boolean.arr,
m_val.data.arr_boolean.size);
}
ArrayRef<double> GetDoubleArray() const {
assert(m_val.type == NT_DOUBLE_ARRAY);
return ArrayRef<double>(m_val.data.arr_double.arr,
m_val.data.arr_double.size);
}
ArrayRef<std::string> GetStringArray() const {
assert(m_val.type == NT_STRING_ARRAY);
return m_string_array;
}
static std::shared_ptr<Value> MakeBoolean(bool value) {
auto val = std::make_shared<Value>(NT_BOOLEAN, private_init());
val->m_val.data.v_boolean = value;
return val;
}
static std::shared_ptr<Value> MakeDouble(double value) {
auto val = std::make_shared<Value>(NT_DOUBLE, private_init());
val->m_val.data.v_double = value;
return val;
}
static std::shared_ptr<Value> MakeString(StringRef value) {
auto val = std::make_shared<Value>(NT_STRING, private_init());
val->m_string = value;
val->m_val.data.v_string.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_string.len = val->m_string.size();
return val;
}
#ifdef _MSC_VER
template <typename T,
typename = std::enable_if_t<std::is_same<T, std::string>>>
#else
template <typename T,
typename std::enable_if<std::is_same<T, std::string>::value>::type>
#endif
static std::shared_ptr<Value> MakeString(T&& value) {
auto val = std::make_shared<Value>(NT_STRING, private_init());
val->m_string = std::move(value);
val->m_val.data.v_string.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_string.len = val->m_string.size();
return val;
}
static std::shared_ptr<Value> MakeRaw(StringRef value) {
auto val = std::make_shared<Value>(NT_RAW, private_init());
val->m_string = value;
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
#ifdef _MSC_VER
template <typename T,
typename = std::enable_if_t<std::is_same<T, std::string>>>
#else
template <typename T,
typename std::enable_if<std::is_same<T, std::string>::value>::type>
#endif
static std::shared_ptr<Value> MakeRaw(T&& value) {
auto val = std::make_shared<Value>(NT_RAW, private_init());
val->m_string = std::move(value);
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
static std::shared_ptr<Value> MakeRpc(StringRef value) {
auto val = std::make_shared<Value>(NT_RPC, private_init());
val->m_string = value;
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
template <typename T>
static std::shared_ptr<Value> MakeRpc(T&& value) {
auto val = std::make_shared<Value>(NT_RPC, private_init());
val->m_string = std::move(value);
val->m_val.data.v_raw.str = const_cast<char*>(val->m_string.c_str());
val->m_val.data.v_raw.len = val->m_string.size();
return val;
}
static std::shared_ptr<Value> MakeBooleanArray(ArrayRef<int> value);
static std::shared_ptr<Value> MakeDoubleArray(ArrayRef<double> value);
static std::shared_ptr<Value> MakeStringArray(ArrayRef<std::string> value);
// Note: This function moves the values out of the vector.
static std::shared_ptr<Value> MakeStringArray(
std::vector<std::string>&& value);
Value(const Value&) = delete;
Value& operator=(const Value&) = delete;
friend bool operator==(const Value& lhs, const Value& rhs);
private:
NT_Value m_val;
std::string m_string;
std::vector<std::string> m_string_array;
};
bool operator==(const Value& lhs, const Value& rhs);
inline bool operator!=(const Value& lhs, const Value& rhs) {
return !(lhs == rhs);
}
} // namespace nt
#endif // NT_VALUE_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -11,15 +11,19 @@
#include <memory>
#include "llvm/StringRef.h"
#include "nt_Value.h"
#include "networktables/NetworkTableValue.h"
#include "support/deprecated.h"
namespace nt {
class NetworkTable;
} // namespace nt
class ITableListener;
/**
* A table whose values can be read and written to
*/
class ITable {
class WPI_DEPRECATED("Use NetworkTable directly") ITable {
public:
/**
* Determines whether the given key is in this table.
@@ -45,7 +49,7 @@ class ITable {
* @param key the name of the table relative to this one
* @return a sub table relative to this one
*/
virtual std::shared_ptr<ITable> GetSubTable(llvm::StringRef key) const = 0;
virtual std::shared_ptr<nt::NetworkTable> GetSubTable(llvm::StringRef key) const = 0;
/**
* @param types bitmask of types; 0 is treated as a "don't care".

View File

@@ -8,14 +8,22 @@
#include <memory>
#include "llvm/StringRef.h"
#include "nt_Value.h"
#include "networktables/NetworkTableValue.h"
#include "support/deprecated.h"
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
class ITable;
/**
* A listener that listens to changes in values in a {@link ITable}
*/
class ITableListener {
class WPI_DEPRECATED(
"Use EntryListener, TableEntryListener, or TableListener as appropriate")
ITableListener {
public:
virtual ~ITableListener() = default;
/**
@@ -44,4 +52,8 @@ class ITableListener {
unsigned int flags);
};
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif /* ITABLELISTENER_H_ */