From c5d456f3a60bb588fbff93d553d7dc18df4c39cb Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Wed, 16 Sep 2015 00:50:31 -0700 Subject: [PATCH] Add ITable/NetworkTable GetKeys and GetSubTables accessors. --- include/networktables/NetworkTable.h | 11 +++++ include/tables/ITable.h | 11 +++++ java/lib/NetworkTablesJNI.cpp | 34 +++++++++++++ .../wpilibj/networktables/NetworkTable.java | 48 ++++++++++++++++--- .../networktables/NetworkTablesJNI.java | 2 +- .../edu/wpi/first/wpilibj/tables/ITable.java | 17 +++++++ src/networktables/NetworkTable.cpp | 26 ++++++++++ 7 files changed, 141 insertions(+), 8 deletions(-) diff --git a/include/networktables/NetworkTable.h b/include/networktables/NetworkTable.h index 1724b93b2f..e4ef8daa5c 100644 --- a/include/networktables/NetworkTable.h +++ b/include/networktables/NetworkTable.h @@ -146,6 +146,17 @@ class NetworkTable : public ITable { bool ContainsSubTable(llvm::StringRef key) const; + /** + * @param types bitmask of types; 0 is treated as a "don't care". + * @return keys currently in the table + */ + std::vector GetKeys(int types = 0) const; + + /** + * @return subtables currently in the table + */ + std::vector GetSubTables() const; + /** * Makes a key's value persistent through program restarts. * diff --git a/include/tables/ITable.h b/include/tables/ITable.h index 8b594348b8..73eb1d83d9 100644 --- a/include/tables/ITable.h +++ b/include/tables/ITable.h @@ -43,6 +43,17 @@ class ITable { */ virtual std::shared_ptr GetSubTable(llvm::StringRef key) const = 0; + /** + * @param types bitmask of types; 0 is treated as a "don't care". + * @return keys currently in the table + */ + virtual std::vector GetKeys(int types = 0) const = 0; + + /** + * @return subtables currently in the table + */ + virtual std::vector GetSubTables() const = 0; + /** * Makes a key's value persistent through program restarts. * diff --git a/java/lib/NetworkTablesJNI.cpp b/java/lib/NetworkTablesJNI.cpp index 8156b9a013..4063b9b544 100644 --- a/java/lib/NetworkTablesJNI.cpp +++ b/java/lib/NetworkTablesJNI.cpp @@ -15,6 +15,7 @@ static jclass booleanCls = nullptr; static jclass doubleCls = nullptr; static jclass stringCls = nullptr; static jclass connectionInfoCls = nullptr; +static jclass entryInfoCls = nullptr; static jclass keyNotDefinedEx = nullptr; static jclass persistentEx = nullptr; @@ -52,6 +53,12 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { if (!connectionInfoCls) return JNI_ERR; env->DeleteLocalRef(local); + local = env->FindClass("edu/wpi/first/wpilibj/networktables/EntryInfo"); + if (!local) return JNI_ERR; + entryInfoCls = static_cast(env->NewGlobalRef(local)); + if (!entryInfoCls) return JNI_ERR; + env->DeleteLocalRef(local); + local = env->FindClass("edu/wpi/first/wpilibj/networktables/NetworkTableKeyNotDefined"); keyNotDefinedEx = static_cast(env->NewGlobalRef(local)); @@ -76,6 +83,7 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { if (doubleCls) env->DeleteGlobalRef(doubleCls); if (stringCls) env->DeleteGlobalRef(stringCls); if (connectionInfoCls) env->DeleteGlobalRef(connectionInfoCls); + if (entryInfoCls) env->DeleteGlobalRef(entryInfoCls); if (keyNotDefinedEx) env->DeleteGlobalRef(keyNotDefinedEx); if (persistentEx) env->DeleteGlobalRef(persistentEx); jvm = nullptr; @@ -347,6 +355,14 @@ static jobject ToJavaObject(JNIEnv *env, const nt::ConnectionInfo &info) { (jlong)info.last_update, (jint)info.protocol_version); } +static jobject ToJavaObject(JNIEnv *env, const nt::EntryInfo &info) { + static jmethodID constructor = + env->GetMethodID(entryInfoCls, "", "(Ljava/lang/String;IIJ)V"); + JavaLocal name(env, ToJavaString(env, info.name)); + return env->NewObject(entryInfoCls, constructor, name.obj(), (jint)info.type, + (jint)info.flags, (jlong)info.last_change); +} + // // Exception throwers // @@ -836,6 +852,24 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI nt::DeleteAllEntries(); } +/* + * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI + * Method: getEntries + * Signature: (Ljava/lang/String;I)[Ledu/wpi/first/wpilibj/networktables/EntryInfo; + */ +JNIEXPORT jobjectArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_getEntries + (JNIEnv *env, jclass, jstring prefix, jint types) +{ + auto arr = nt::GetEntryInfo(JavaStringRef(env, prefix), types); + jobjectArray jarr = env->NewObjectArray(arr.size(), entryInfoCls, nullptr); + if (!jarr) return nullptr; + for (size_t i = 0; i < arr.size(); ++i) { + JavaLocal jelem(env, ToJavaObject(env, arr[i])); + env->SetObjectArrayElement(jarr, i, jelem); + } + return jarr; +} + /* * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI * Method: flush diff --git a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java index 0f45c40c1f..0c4430a2d1 100644 --- a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java +++ b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java @@ -367,13 +367,47 @@ public class NetworkTable implements ITable, IRemote { } public boolean containsSubTable(String key) { - String subtablePrefix = path + key + PATH_SEPARATOR; - //List keys = node.getEntryStore().keys(); - //for (int i = 0; i < keys.size(); ++i) { - // if (((String)keys.get(i)).startsWith(subtablePrefix)) - // return true; - //} - return false; + EntryInfo[] entries = NetworkTablesJNI.getEntries(path + PATH_SEPARATOR + key + PATH_SEPARATOR, 0); + return entries.length != 0; + } + + /** + * @param types bitmask of types; 0 is treated as a "don't care". + * @return keys currently in the table + */ + public Set getKeys(int types) { + Set keys = new HashSet(); + int prefixLen = path.length() + 1; + for (EntryInfo entry : NetworkTablesJNI.getEntries(path + PATH_SEPARATOR, types)) { + String relativeKey = entry.name.substring(prefixLen); + if (relativeKey.indexOf(PATH_SEPARATOR) != -1) + continue; + keys.add(relativeKey); + } + return keys; + } + + /** + * @return keys currently in the table + */ + public Set getKeys() { + return getKeys(0); + } + + /** + * @return subtables currently in the table + */ + public Set getSubTables() { + Set keys = new HashSet(); + int prefixLen = path.length() + 1; + for (EntryInfo entry : NetworkTablesJNI.getEntries(path + PATH_SEPARATOR, 0)) { + String relativeKey = entry.name.substring(prefixLen); + int endSubTable = relativeKey.indexOf(PATH_SEPARATOR); + if (endSubTable == -1) + continue; + keys.add(relativeKey.substring(0, endSubTable)); + } + return keys; } /** diff --git a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java index 202cd4aab3..a613b0d8b9 100644 --- a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java +++ b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java @@ -98,7 +98,7 @@ public class NetworkTablesJNI { public static native void deleteEntry(String key); public static native void deleteAllEntries(); - // public static native EntryInfo[] getEntryInfo(String prefix, int types); + public static native EntryInfo[] getEntries(String prefix, int types); public static native void flush(); diff --git a/java/src/edu/wpi/first/wpilibj/tables/ITable.java b/java/src/edu/wpi/first/wpilibj/tables/ITable.java index b5c62e3867..62b37d30ef 100644 --- a/java/src/edu/wpi/first/wpilibj/tables/ITable.java +++ b/java/src/edu/wpi/first/wpilibj/tables/ITable.java @@ -1,6 +1,7 @@ package edu.wpi.first.wpilibj.tables; import java.util.NoSuchElementException; +import java.util.Set; /** @@ -30,6 +31,22 @@ public interface ITable { */ public ITable getSubTable(String key); + /** + * @param types bitmask of types; 0 is treated as a "don't care". + * @return keys currently in the table + */ + public Set getKeys(int types); + + /** + * @return keys currently in the table + */ + public Set getKeys(); + + /** + * @return subtables currently in the table + */ + public Set getSubTables(); + /** * Makes a key's value persistent through program restarts. * The key cannot be null. diff --git a/src/networktables/NetworkTable.cpp b/src/networktables/NetworkTable.cpp index 51cb94981e..11347e07ce 100644 --- a/src/networktables/NetworkTable.cpp +++ b/src/networktables/NetworkTable.cpp @@ -161,6 +161,32 @@ bool NetworkTable::ContainsSubTable(StringRef key) const { return !nt::GetEntryInfo(path, 0).empty(); } +std::vector NetworkTable::GetKeys(int types) const { + std::vector keys; + llvm::SmallString<128> path(m_path); + path += PATH_SEPARATOR_CHAR; + for (auto& entry : nt::GetEntryInfo(path, types)) { + auto relative_key = StringRef(entry.name).substr(path.size()); + if (relative_key.find(PATH_SEPARATOR_CHAR) != StringRef::npos) + continue; + keys.push_back(relative_key); + } + return keys; +} + +std::vector NetworkTable::GetSubTables() const { + std::vector keys; + llvm::SmallString<128> path(m_path); + path += PATH_SEPARATOR_CHAR; + for (auto& entry : nt::GetEntryInfo(path, 0)) { + auto relative_key = StringRef(entry.name).substr(path.size()); + std::size_t end_subtable = relative_key.find(PATH_SEPARATOR_CHAR); + if (end_subtable == StringRef::npos) continue; + keys.push_back(relative_key.substr(0, end_subtable)); + } + return keys; +} + void NetworkTable::SetPersistent(StringRef key) { SetFlags(key, NT_PERSISTENT); }