From c76e60324b89a4775bca0c60bb347d0bc8f3a975 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 20 Nov 2015 01:22:26 -0800 Subject: [PATCH] Add Java support for raw values. Either ByteBuffer or byte[] can be used for putRaw(). getRaw() returns byte[]. --- java/lib/NetworkTablesJNI.cpp | 67 ++++++++++++++++++- .../wpilibj/networktables/NetworkTable.java | 64 ++++++++++++++++++ .../networktables/NetworkTablesJNI.java | 5 ++ .../edu/wpi/first/wpilibj/tables/ITable.java | 31 +++++++++ 4 files changed, 164 insertions(+), 3 deletions(-) diff --git a/java/lib/NetworkTablesJNI.cpp b/java/lib/NetworkTablesJNI.cpp index ced9f20877..b0d0f99290 100644 --- a/java/lib/NetworkTablesJNI.cpp +++ b/java/lib/NetworkTablesJNI.cpp @@ -206,6 +206,21 @@ class JavaByteRef { size_t m_size; }; +class JavaByteRefBB { + public: + JavaByteRefBB(JNIEnv *env, jobject bb, int len) + : m_env(env), m_elements(env->GetDirectBufferAddress(bb)), m_size(len) {} + + operator nt::StringRef() const { + return nt::StringRef(reinterpret_cast(m_elements), m_size); + } + + private: + JNIEnv *m_env; + void *m_elements; + size_t m_size; +}; + std::shared_ptr FromJavaRaw(JNIEnv *env, jbyteArray jarr) { size_t len = env->GetArrayLength(jarr); jbyte *elements = @@ -217,6 +232,14 @@ std::shared_ptr FromJavaRaw(JNIEnv *env, jbyteArray jarr) { return rv; } +std::shared_ptr FromJavaRawBB(JNIEnv *env, jobject jbb, int len) { + void* elements = env->GetDirectBufferAddress(jbb); + if (!elements) return nullptr; + auto rv = nt::Value::MakeRaw( + nt::StringRef(reinterpret_cast(elements), len)); + return rv; +} + std::shared_ptr FromJavaRpc(JNIEnv *env, jbyteArray jarr) { size_t len = env->GetArrayLength(jarr); jbyte *elements = @@ -449,7 +472,7 @@ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTable * Method: putRaw * Signature: (Ljava/lang/String;[B)Z */ -JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putRaw +JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putRaw__Ljava_lang_String_2_3B (JNIEnv *env, jclass, jstring key, jbyteArray value) { auto v = FromJavaRaw(env, value); @@ -457,6 +480,19 @@ JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTable return nt::SetEntryValue(JavaStringRef(env, key), v); } +/* + * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI + * Method: putRaw + * Signature: (Ljava/lang/String;Ljava/nio/ByteBuffer;I)Z + */ +JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_putRaw__Ljava_lang_String_2Ljava_nio_ByteBuffer_2I + (JNIEnv *env, jclass, jstring key, jobject value, jint len) +{ + auto v = FromJavaRawBB(env, value, len); + if (!v) return false; + return nt::SetEntryValue(JavaStringRef(env, key), v); +} + /* * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI * Method: putBooleanArray @@ -535,7 +571,7 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI * Method: forcePutRaw * Signature: (Ljava/lang/String;[B)V */ -JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutRaw +JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutRaw__Ljava_lang_String_2_3B (JNIEnv *env, jclass, jstring key, jbyteArray value) { auto v = FromJavaRaw(env, value); @@ -543,6 +579,19 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI nt::SetEntryTypeValue(JavaStringRef(env, key), v); } +/* + * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI + * Method: forcePutRaw + * Signature: (Ljava/lang/String;Ljava/nio/ByteBuffer;I)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_forcePutRaw__Ljava_lang_String_2Ljava_nio_ByteBuffer_2I + (JNIEnv *env, jclass, jstring key, jobject value, jint len) +{ + auto v = FromJavaRawBB(env, value, len); + if (!v) return; + nt::SetEntryTypeValue(JavaStringRef(env, key), v); +} + /* * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI * Method: forcePutBooleanArray @@ -1054,12 +1103,24 @@ JNIEXPORT jbyteArray JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTab * Method: callRpc * Signature: (Ljava/lang/String;[B)I */ -JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_callRpc +JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_callRpc__Ljava_lang_String_2_3B (JNIEnv *env, jclass, jstring key, jbyteArray params) { return nt::CallRpc(JavaStringRef(env, key), JavaByteRef(env, params)); } +/* + * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI + * Method: callRpc + * Signature: (Ljava/lang/String;Ljava/nio/ByteBuffer;I)I + */ +JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_networktables_NetworkTablesJNI_callRpc__Ljava_lang_String_2Ljava_nio_ByteBuffer_2I + (JNIEnv *env, jclass, jstring key, jobject params, jint params_len) +{ + return nt::CallRpc(JavaStringRef(env, key), + JavaByteRefBB(env, params, params_len)); +} + /* * Class: edu_wpi_first_wpilibj_networktables_NetworkTablesJNI * Method: setNetworkIdentity diff --git a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java index 23bd6e3dbe..ec5743214d 100644 --- a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java +++ b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTable.java @@ -3,6 +3,7 @@ package edu.wpi.first.wpilibj.networktables; import edu.wpi.first.wpilibj.tables.*; import edu.wpi.first.wpilibj.networktables2.type.*; import java.io.*; +import java.nio.ByteBuffer; import java.util.*; /** @@ -765,6 +766,69 @@ public class NetworkTable implements ITable, IRemote { return NetworkTablesJNI.getStringArray(path + PATH_SEPARATOR + key, defaultValue); } + /** + * Maps the specified key to the specified value in this table. The key can + * not be null. The value can be retrieved by calling the get method with a + * key that is equal to the original key. + * + * @param key + * the key + * @param value + * the value + * @return False if the table key already exists with a different type + */ + public boolean putRaw(String key, byte[] value) { + return NetworkTablesJNI.putRaw(path + PATH_SEPARATOR + key, value); + } + + /** + * Maps the specified key to the specified value in this table. The key can + * not be null. The value can be retrieved by calling the get method with a + * key that is equal to the original key. + * + * @param key + * the key + * @param value + * the value + * @param len + * the length of the value + * @return False if the table key already exists with a different type + */ + public boolean putRaw(String key, ByteBuffer value, int len) { + if (!value.isDirect()) + throw new IllegalArgumentException("must be a direct buffer"); + if (value.capacity() < len) + throw new IllegalArgumentException("buffer is too small, must be at least " + len); + return NetworkTablesJNI.putRaw(path + PATH_SEPARATOR + key, value, len); + } + + /** + * Returns the key that the name maps to. + * + * @param key + * the key name + * @return the key + * @throws TableKeyNotDefinedException + * if the specified key is null + */ + public byte[] getRaw(String key) throws TableKeyNotDefinedException { + return NetworkTablesJNI.getRaw(path + PATH_SEPARATOR + key); + } + + /** + * Returns the key that the name maps to. If the key is null, it will return + * the default value + * + * @param key + * the key name + * @param defaultValue + * the default value if the key is null + * @return the key + */ + public byte[] getRaw(String key, byte[] defaultValue) { + return NetworkTablesJNI.getRaw(path + PATH_SEPARATOR + key, defaultValue); + } + /** * Maps the specified key to the specified value in this table. The key can * not be null. The value can be retrieved by calling the get method with a diff --git a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java index d48778fba2..810d7f89f2 100644 --- a/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java +++ b/java/src/edu/wpi/first/wpilibj/networktables/NetworkTablesJNI.java @@ -7,6 +7,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; public class NetworkTablesJNI { static boolean libraryLoaded = false; @@ -70,6 +71,7 @@ public class NetworkTablesJNI { public static native boolean putDouble(String key, double value); public static native boolean putString(String key, String value); public static native boolean putRaw(String key, byte[] value); + public static native boolean putRaw(String key, ByteBuffer value, int len); public static native boolean putBooleanArray(String key, boolean[] value); public static native boolean putDoubleArray(String key, double[] value); public static native boolean putStringArray(String key, String[] value); @@ -78,6 +80,7 @@ public class NetworkTablesJNI { public static native void forcePutDouble(String key, double value); public static native void forcePutString(String key, String value); public static native void forcePutRaw(String key, byte[] value); + public static native void forcePutRaw(String key, ByteBuffer value, int len); public static native void forcePutBooleanArray(String key, boolean[] value); public static native void forcePutDoubleArray(String key, double[] value); public static native void forcePutStringArray(String key, String[] value); @@ -123,9 +126,11 @@ public class NetworkTablesJNI { public static native void removeConnectionListener(int connListenerUid); // public static native void createRpc(String key, byte[] def, IRpc rpc); + // public static native void createRpc(String key, ByteBuffer def, int def_len, IRpc rpc); public static native byte[] getRpc(String key) throws TableKeyNotDefinedException; public static native byte[] getRpc(String key, byte[] defaultValue); public static native int callRpc(String key, byte[] params); + public static native int callRpc(String key, ByteBuffer params, int params_len); // public static native byte[] getRpcResultBlocking(int callUid); // public static native byte[] getRpcResultNonblocking(int callUid) throws RpcNoResponseException; diff --git a/java/src/edu/wpi/first/wpilibj/tables/ITable.java b/java/src/edu/wpi/first/wpilibj/tables/ITable.java index 42fb73ddc4..44ab586d74 100644 --- a/java/src/edu/wpi/first/wpilibj/tables/ITable.java +++ b/java/src/edu/wpi/first/wpilibj/tables/ITable.java @@ -1,5 +1,6 @@ package edu.wpi.first.wpilibj.tables; +import java.nio.ByteBuffer; import java.util.NoSuchElementException; import java.util.Set; @@ -297,6 +298,36 @@ public interface ITable { */ public String[] getStringArray(String key, String[] defaultValue); + /** + * Put a raw value (byte array) in the table + * @param key the key to be assigned to + * @param value the value that will be assigned + * @return False if the table key already exists with a different type + */ + public boolean putRaw(String key, byte[] value); + /** + * Put a raw value (bytes from a byte buffer) in the table + * @param key the key to be assigned to + * @param value the value that will be assigned + * @param len the length of the value + * @return False if the table key already exists with a different type + */ + public boolean putRaw(String key, ByteBuffer value, int len); + /** + * @param key the key to look up + * @return the value associated with the given key + * @throws TableKeyNotDefinedException if there is no value associated with + * the given key + */ + public byte[] getRaw(String key) throws TableKeyNotDefinedException; + /** + * @param key the key to look up + * @param defaultValue the value to be returned if no value is found + * @return the value associated with the given key or the given default value + * if there is no value associated with the key + */ + public byte[] getRaw(String key, byte[] defaultValue); + /** Notifier flag values. */ public static final int NOTIFY_IMMEDIATE = 0x01; public static final int NOTIFY_LOCAL = 0x02;