mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[ntcore] Enhance Java raw value support
Add support for start, length, and ByteBuffers
This commit is contained in:
@@ -22,6 +22,8 @@ static JClass timestamped{{ t.TypeName }}Cls;
|
||||
static JClass {{ t.jni.jtype }}Cls;
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
static JException illegalArgEx;
|
||||
static JException indexOobEx;
|
||||
static JException nullPointerEx;
|
||||
|
||||
static const JClassInit classes[] = {
|
||||
@@ -36,6 +38,8 @@ static const JClassInit classes[] = {
|
||||
};
|
||||
|
||||
static const JExceptionInit exceptions[] = {
|
||||
{"java/lang/IllegalArgumentException", &illegalArgEx},
|
||||
{"java/lang/IndexOutOfBoundsException", &indexOobEx},
|
||||
{"java/lang/NullPointerException", &nullPointerEx},
|
||||
};
|
||||
|
||||
@@ -65,6 +69,9 @@ void JNI_UnloadTypes(JNIEnv* env) {
|
||||
for (auto& c : classes) {
|
||||
c.cls->free(env);
|
||||
}
|
||||
for (auto& c : exceptions) {
|
||||
c.cls->free(env);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nt
|
||||
@@ -185,7 +192,65 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_readQueueValues{{ t.TypeName }
|
||||
{
|
||||
return {{ t.jni.ToJavaArray }}(env, nt::ReadQueueValues{{ t.TypeName }}(subentry));
|
||||
}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: setRaw
|
||||
* Signature: (IJ[BII)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_setRaw
|
||||
(JNIEnv* env, jclass, jint entry, jlong time, jbyteArray value, jint start, jint len)
|
||||
{
|
||||
if (!value) {
|
||||
nullPointerEx.Throw(env, "value is null");
|
||||
return false;
|
||||
}
|
||||
if (start < 0) {
|
||||
indexOobEx.Throw(env, "start must be >= 0");
|
||||
return false;
|
||||
}
|
||||
if (len < 0) {
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
CriticalJByteArrayRef cvalue{env, value};
|
||||
if (static_cast<unsigned int>(start + len) > cvalue.size()) {
|
||||
indexOobEx.Throw(env, "start + len must be smaller than array length");
|
||||
return false;
|
||||
}
|
||||
return nt::SetRaw(entry, cvalue.uarray().subspan(start, len), time);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: setRawBuffer
|
||||
* Signature: (IJLjava/nio/ByteBuffer;II)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_setRawBuffer
|
||||
(JNIEnv* env, jclass, jint entry, jlong time, jobject value, jint start, jint len)
|
||||
{
|
||||
if (!value) {
|
||||
nullPointerEx.Throw(env, "value is null");
|
||||
return false;
|
||||
}
|
||||
if (start < 0) {
|
||||
indexOobEx.Throw(env, "start must be >= 0");
|
||||
return false;
|
||||
}
|
||||
if (len < 0) {
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
JByteArrayRef cvalue{env, value, start + len};
|
||||
if (!cvalue) {
|
||||
illegalArgEx.Throw(env, "value must be a native ByteBuffer");
|
||||
return false;
|
||||
}
|
||||
return nt::SetRaw(entry, cvalue.uarray().subspan(start, len), time);
|
||||
}
|
||||
{% else %}
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: set{{ t.TypeName }}
|
||||
@@ -203,7 +268,7 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_set{{ t.TypeName }}
|
||||
{%- endif %}
|
||||
return nt::Set{{ t.TypeName }}(entry, {{ t.jni.FromJavaBegin }}value{{ t.jni.FromJavaEnd }}, time);
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: get{{ t.TypeName }}
|
||||
@@ -223,7 +288,65 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_get{{ t.TypeName }}
|
||||
return nt::Get{{ t.TypeName }}(entry, defaultValue);
|
||||
{%- endif %}
|
||||
}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: setDefaultRaw
|
||||
* Signature: (IJ[BII)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_setDefaultRaw
|
||||
(JNIEnv* env, jclass, jint entry, jlong, jbyteArray defaultValue, jint start, jint len)
|
||||
{
|
||||
if (!defaultValue) {
|
||||
nullPointerEx.Throw(env, "value is null");
|
||||
return false;
|
||||
}
|
||||
if (start < 0) {
|
||||
indexOobEx.Throw(env, "start must be >= 0");
|
||||
return false;
|
||||
}
|
||||
if (len < 0) {
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
CriticalJByteArrayRef cvalue{env, defaultValue};
|
||||
if (static_cast<unsigned int>(start + len) > cvalue.size()) {
|
||||
indexOobEx.Throw(env, "start + len must be smaller than array length");
|
||||
return false;
|
||||
}
|
||||
return nt::SetDefaultRaw(entry, cvalue.uarray().subspan(start, len));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: setDefaultRawBuffer
|
||||
* Signature: (IJLjava/nio/ByteBuffer;II)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_networktables_NetworkTablesJNI_setDefaultRawBuffer
|
||||
(JNIEnv* env, jclass, jint entry, jlong, jobject defaultValue, jint start, jint len)
|
||||
{
|
||||
if (!defaultValue) {
|
||||
nullPointerEx.Throw(env, "value is null");
|
||||
return false;
|
||||
}
|
||||
if (start < 0) {
|
||||
indexOobEx.Throw(env, "start must be >= 0");
|
||||
return false;
|
||||
}
|
||||
if (len < 0) {
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
JByteArrayRef cvalue{env, defaultValue, start + len};
|
||||
if (!cvalue) {
|
||||
illegalArgEx.Throw(env, "value must be a native ByteBuffer");
|
||||
return false;
|
||||
}
|
||||
return nt::SetDefaultRaw(entry, cvalue.uarray().subspan(start, len));
|
||||
}
|
||||
{% else %}
|
||||
/*
|
||||
* Class: edu_wpi_first_networktables_NetworkTablesJNI
|
||||
* Method: setDefault{{ t.TypeName }}
|
||||
@@ -241,5 +364,6 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setDefault{{ t.TypeName }}
|
||||
{%- endif %}
|
||||
return nt::SetDefault{{ t.TypeName }}(entry, {{ t.jni.FromJavaBegin }}defaultValue{{ t.jni.FromJavaEnd }});
|
||||
}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
} // extern "C"
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.networktables;
|
||||
|
||||
{% if TypeName == "Raw" %}
|
||||
import java.nio.ByteBuffer;
|
||||
{% endif %}
|
||||
/** NetworkTables {{ TypeName }} implementation. */
|
||||
@SuppressWarnings("PMD.ArrayIsStoredDirectly")
|
||||
final class {{ TypeName }}EntryImpl extends EntryBase implements {{ TypeName }}Entry {
|
||||
@@ -54,7 +56,27 @@ final class {{ TypeName }}EntryImpl extends EntryBase implements {{ TypeName }}E
|
||||
public {{ java.ValueType }}[] readQueueValues() {
|
||||
return NetworkTablesJNI.readQueueValues{{ TypeName }}(m_handle);
|
||||
}
|
||||
{% if TypeName == "Raw" %}
|
||||
@Override
|
||||
public void set(byte[] value, int start, int len, long time) {
|
||||
NetworkTablesJNI.setRaw(m_handle, time, value, start, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(ByteBuffer value, int start, int len, long time) {
|
||||
NetworkTablesJNI.setRaw(m_handle, time, value, start, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(byte[] value, int start, int len) {
|
||||
NetworkTablesJNI.setDefaultRaw(m_handle, 0, value, start, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault(ByteBuffer value, int start, int len) {
|
||||
NetworkTablesJNI.setDefaultRaw(m_handle, 0, value, start, len);
|
||||
}
|
||||
{% else %}
|
||||
@Override
|
||||
public void set({{ java.ValueType }} value, long time) {
|
||||
NetworkTablesJNI.set{{ TypeName }}(m_handle, time, value);
|
||||
@@ -64,7 +86,7 @@ final class {{ TypeName }}EntryImpl extends EntryBase implements {{ TypeName }}E
|
||||
public void setDefault({{ java.ValueType }} value) {
|
||||
NetworkTablesJNI.setDefault{{ TypeName }}(m_handle, 0, value);
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
@Override
|
||||
public void unpublish() {
|
||||
NetworkTablesJNI.unpublish(m_handle);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
package edu.wpi.first.networktables;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/** NetworkTables generic implementation. */
|
||||
final class GenericEntryImpl extends EntryBase implements GenericEntry {
|
||||
/**
|
||||
@@ -140,6 +142,33 @@ final class GenericEntryImpl extends EntryBase implements GenericEntry {
|
||||
}
|
||||
}
|
||||
{% for t in types %}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
*
|
||||
* @param value the value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
@Override
|
||||
public boolean setRaw(byte[] value, int start, int len, long time) {
|
||||
return NetworkTablesJNI.setRaw(m_handle, time, value, start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
*
|
||||
* @param value the value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
@Override
|
||||
public boolean setRaw(ByteBuffer value, int start, int len, long time) {
|
||||
return NetworkTablesJNI.setRaw(m_handle, time, value, start, len);
|
||||
}
|
||||
{% else %}
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
*
|
||||
@@ -150,6 +179,7 @@ final class GenericEntryImpl extends EntryBase implements GenericEntry {
|
||||
public boolean set{{ t.TypeName }}({{ t.java.ValueType }} value, long time) {
|
||||
return NetworkTablesJNI.set{{ t.TypeName }}(m_handle, time, value);
|
||||
}
|
||||
{% endif -%}
|
||||
{% if t.java.WrapValueType %}
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
@@ -265,6 +295,33 @@ final class GenericEntryImpl extends EntryBase implements GenericEntry {
|
||||
}
|
||||
}
|
||||
{% for t in types %}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
@Override
|
||||
public boolean setDefaultRaw(byte[] defaultValue, int start, int len) {
|
||||
return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue, start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
@Override
|
||||
public boolean setDefaultRaw(ByteBuffer defaultValue, int start, int len) {
|
||||
return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue, start, len);
|
||||
}
|
||||
{% else %}
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
@@ -275,6 +332,7 @@ final class GenericEntryImpl extends EntryBase implements GenericEntry {
|
||||
public boolean setDefault{{ t.TypeName }}({{ t.java.ValueType }} defaultValue) {
|
||||
return NetworkTablesJNI.setDefault{{ t.TypeName }}(m_handle, 0, defaultValue);
|
||||
}
|
||||
{% endif -%}
|
||||
{% if t.java.WrapValueType %}
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
package edu.wpi.first.networktables;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/** NetworkTables generic publisher. */
|
||||
@@ -54,7 +55,86 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
default boolean set{{ t.TypeName }}({{ t.java.ValueType }} value) {
|
||||
return set{{ t.TypeName }}(value, 0);
|
||||
}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
default boolean setRaw(ByteBuffer value) {
|
||||
return setRaw(value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
default boolean setRaw(byte[] value, long time) {
|
||||
return setRaw(value, 0, value.length, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish; will send from value.position() to value.limit()
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
default boolean setRaw(ByteBuffer value, long time) {
|
||||
int pos = value.position();
|
||||
return setRaw(value, pos, value.limit() - pos, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
default boolean setRaw(byte[] value, int start, int len) {
|
||||
return setRaw(value, start, len, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
boolean setRaw(byte[] value, int start, int len, long time);
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
default boolean setRaw(ByteBuffer value, int start, int len) {
|
||||
return setRaw(value, start, len, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
boolean setRaw(ByteBuffer value, int start, int len, long time);
|
||||
{% else %}
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
@@ -63,6 +143,7 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
* @return False if the topic already exists with a different type
|
||||
*/
|
||||
boolean set{{ t.TypeName }}({{ t.java.ValueType }} value, long time);
|
||||
{% endif -%}
|
||||
{% if t.java.WrapValueType %}
|
||||
/**
|
||||
* Publish a new value.
|
||||
@@ -101,6 +182,49 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
*/
|
||||
boolean setDefaultValue(Object defaultValue);
|
||||
{% for t in types %}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
default boolean setDefaultRaw(byte[] defaultValue) {
|
||||
return setDefaultRaw(defaultValue, 0, defaultValue.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set; will send from defaultValue.position() to
|
||||
* defaultValue.limit()
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
default boolean setDefaultRaw(ByteBuffer defaultValue) {
|
||||
int pos = defaultValue.position();
|
||||
return setDefaultRaw(defaultValue, pos, defaultValue.limit() - pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefaultRaw(byte[] defaultValue, int start, int len);
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefaultRaw(ByteBuffer defaultValue, int start, int len);
|
||||
{% else %}
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
@@ -108,6 +232,7 @@ public interface GenericPublisher extends Publisher, Consumer<NetworkTableValue>
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
boolean setDefault{{ t.TypeName }}({{ t.java.ValueType }} defaultValue);
|
||||
{% endif -%}
|
||||
{% if t.java.WrapValueType %}
|
||||
boolean setDefault{{ t.TypeName }}({{ t.java.WrapValueType }} defaultValue);
|
||||
{% endif -%}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
package edu.wpi.first.networktables;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* NetworkTables Entry.
|
||||
*
|
||||
@@ -310,6 +312,42 @@ public final class NetworkTableEntry implements Publisher, Subscriber {
|
||||
public boolean setDefault{{ t.TypeName }}({{ t.java.ValueType }} defaultValue) {
|
||||
return NetworkTablesJNI.setDefault{{ t.TypeName }}(m_handle, 0, defaultValue);
|
||||
}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set; will send from defaultValue.position() to
|
||||
* defaultValue.capacity()
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
public boolean setDefaultRaw(ByteBuffer defaultValue) {
|
||||
return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
public boolean setDefaultRaw(byte[] defaultValue, int start, int len) {
|
||||
return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue, start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
*
|
||||
* @param defaultValue the default value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
public boolean setDefaultRaw(ByteBuffer defaultValue, int start, int len) {
|
||||
return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue, start, len);
|
||||
}
|
||||
{% endif -%}
|
||||
{% if t.java.WrapValueType %}
|
||||
/**
|
||||
* Sets the entry's value if it does not exist.
|
||||
@@ -427,6 +465,41 @@ public final class NetworkTableEntry implements Publisher, Subscriber {
|
||||
public boolean set{{ t.TypeName }}({{ t.java.ValueType }} value) {
|
||||
return NetworkTablesJNI.set{{ t.TypeName }}(m_handle, 0, value);
|
||||
}
|
||||
{% if t.TypeName == "Raw" %}
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
*
|
||||
* @param value the value to set; will send from value.position() to value.capacity()
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
public boolean setRaw(ByteBuffer value) {
|
||||
return NetworkTablesJNI.setRaw(m_handle, 0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
*
|
||||
* @param value the value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
public boolean setRaw(byte[] value, int start, int len) {
|
||||
return NetworkTablesJNI.setRaw(m_handle, 0, value, start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
*
|
||||
* @param value the value to set
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @return False if the entry exists with a different type
|
||||
*/
|
||||
public boolean setRaw(ByteBuffer value, int start, int len) {
|
||||
return NetworkTablesJNI.setRaw(m_handle, 0, value, start, len);
|
||||
}
|
||||
{% endif -%}
|
||||
{% if t.java.WrapValueType %}
|
||||
/**
|
||||
* Sets the entry's value.
|
||||
|
||||
@@ -7,6 +7,7 @@ package edu.wpi.first.networktables;
|
||||
import edu.wpi.first.util.RuntimeLoader;
|
||||
import edu.wpi.first.util.datalog.DataLog;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.EnumSet;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -182,12 +183,77 @@ public final class NetworkTablesJNI {
|
||||
public static native Timestamped{{ t.TypeName }}[] readQueue{{ t.TypeName }}(int subentry);
|
||||
|
||||
public static native {{ t.java.ValueType }}[] readQueueValues{{ t.TypeName }}(int subentry);
|
||||
{% if t.TypeName == "Raw" %}
|
||||
public static boolean setRaw(int entry, long time, byte[] value) {
|
||||
return setRaw(entry, time, value, 0, value.length);
|
||||
}
|
||||
|
||||
public static native boolean setRaw(int entry, long time, byte[] value, int start, int len);
|
||||
|
||||
public static boolean setRaw(int entry, long time, ByteBuffer value) {
|
||||
int pos = value.position();
|
||||
return setRaw(entry, time, value, pos, value.capacity() - pos);
|
||||
}
|
||||
|
||||
public static boolean setRaw(int entry, long time, ByteBuffer value, int start, int len) {
|
||||
if (value.isDirect()) {
|
||||
if (start < 0) {
|
||||
throw new IndexOutOfBoundsException("start must be >= 0");
|
||||
}
|
||||
if (len < 0) {
|
||||
throw new IndexOutOfBoundsException("len must be >= 0");
|
||||
}
|
||||
if ((start + len) > value.capacity()) {
|
||||
throw new IndexOutOfBoundsException("start + len must be smaller than buffer capacity");
|
||||
}
|
||||
return setRawBuffer(entry, time, value, start, len);
|
||||
} else if (value.hasArray()) {
|
||||
return setRaw(entry, time, value.array(), value.arrayOffset() + start, len);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("ByteBuffer must be direct or have a backing array");
|
||||
}
|
||||
}
|
||||
|
||||
private static native boolean setRawBuffer(int entry, long time, ByteBuffer value, int start, int len);
|
||||
{% else %}
|
||||
public static native boolean set{{ t.TypeName }}(int entry, long time, {{ t.java.ValueType }} value);
|
||||
|
||||
{% endif %}
|
||||
public static native {{ t.java.ValueType }} get{{ t.TypeName }}(int entry, {{ t.java.ValueType }} defaultValue);
|
||||
{% if t.TypeName == "Raw" %}
|
||||
public static boolean setDefaultRaw(int entry, long time, byte[] defaultValue) {
|
||||
return setDefaultRaw(entry, time, defaultValue, 0, defaultValue.length);
|
||||
}
|
||||
|
||||
public static native boolean setDefaultRaw(int entry, long time, byte[] defaultValue, int start, int len);
|
||||
|
||||
public static boolean setDefaultRaw(int entry, long time, ByteBuffer defaultValue) {
|
||||
int pos = defaultValue.position();
|
||||
return setDefaultRaw(entry, time, defaultValue, pos, defaultValue.limit() - pos);
|
||||
}
|
||||
|
||||
public static boolean setDefaultRaw(int entry, long time, ByteBuffer defaultValue, int start, int len) {
|
||||
if (defaultValue.isDirect()) {
|
||||
if (start < 0) {
|
||||
throw new IndexOutOfBoundsException("start must be >= 0");
|
||||
}
|
||||
if (len < 0) {
|
||||
throw new IndexOutOfBoundsException("len must be >= 0");
|
||||
}
|
||||
if ((start + len) > defaultValue.capacity()) {
|
||||
throw new IndexOutOfBoundsException("start + len must be smaller than buffer capacity");
|
||||
}
|
||||
return setDefaultRawBuffer(entry, time, defaultValue, start, len);
|
||||
} else if (defaultValue.hasArray()) {
|
||||
return setDefaultRaw(entry, time, defaultValue.array(), defaultValue.arrayOffset() + start, len);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("ByteBuffer must be direct or have a backing array");
|
||||
}
|
||||
}
|
||||
|
||||
private static native boolean setDefaultRawBuffer(int entry, long time, ByteBuffer defaultValue, int start, int len);
|
||||
{% else %}
|
||||
public static native boolean setDefault{{ t.TypeName }}(int entry, long time, {{ t.java.ValueType }} defaultValue);
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
public static native NetworkTableValue[] readQueueValue(int subentry);
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
package edu.wpi.first.networktables;
|
||||
|
||||
{% if TypeName == "Raw" %}
|
||||
import java.nio.ByteBuffer;
|
||||
{% endif -%}
|
||||
import {{ java.ConsumerFunctionPackage|default('java.util.function') }}.{{ java.FunctionTypePrefix }}Consumer;
|
||||
|
||||
/** NetworkTables {{ TypeName }} publisher. */
|
||||
@@ -25,6 +28,124 @@ public interface {{ TypeName }}Publisher extends Publisher, {{ java.FunctionType
|
||||
set(value, 0);
|
||||
}
|
||||
|
||||
{% if TypeName == "Raw" %}
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
*/
|
||||
default void set(byte[] value, long time) {
|
||||
set(value, 0, value.length, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value using current NT time.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
*/
|
||||
default void set(byte[] value, int start, int len) {
|
||||
set(value, start, len, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
*/
|
||||
void set(byte[] value, int start, int len, long time);
|
||||
|
||||
/**
|
||||
* Publish a new value using current NT time.
|
||||
*
|
||||
* @param value value to publish; will send from value.position() to value.limit()
|
||||
*/
|
||||
default void set(ByteBuffer value) {
|
||||
set(value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish; will send from value.position() to value.limit()
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
*/
|
||||
default void set(ByteBuffer value, long time) {
|
||||
int pos = value.position();
|
||||
set(value, pos, value.limit() - pos, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value using current NT time.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
*/
|
||||
default void set(ByteBuffer value, int start, int len) {
|
||||
set(value, start, len, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
* @param value value to publish
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
* @param time timestamp; 0 indicates current NT time should be used
|
||||
*/
|
||||
void set(ByteBuffer value, int start, int len, long time);
|
||||
|
||||
/**
|
||||
* Publish a default value.
|
||||
* On reconnect, a default value will never be used in preference to a
|
||||
* published value.
|
||||
*
|
||||
* @param value value
|
||||
*/
|
||||
default void setDefault(byte[] value) {
|
||||
setDefault(value, 0, value.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a default value.
|
||||
* On reconnect, a default value will never be used in preference to a
|
||||
* published value.
|
||||
*
|
||||
* @param value value
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.length - start)
|
||||
*/
|
||||
void setDefault(byte[] value, int start, int len);
|
||||
|
||||
/**
|
||||
* Publish a default value.
|
||||
* On reconnect, a default value will never be used in preference to a
|
||||
* published value.
|
||||
*
|
||||
* @param value value; will send from value.position() to value.limit()
|
||||
*/
|
||||
default void setDefault(ByteBuffer value) {
|
||||
int pos = value.position();
|
||||
setDefault(value, pos, value.limit() - pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a default value.
|
||||
* On reconnect, a default value will never be used in preference to a
|
||||
* published value.
|
||||
*
|
||||
* @param value value
|
||||
* @param start Start position of data (in buffer)
|
||||
* @param len Length of data (must be less than or equal to value.capacity() - start)
|
||||
*/
|
||||
void setDefault(ByteBuffer value, int start, int len);
|
||||
{% else %}
|
||||
/**
|
||||
* Publish a new value.
|
||||
*
|
||||
@@ -41,7 +162,7 @@ public interface {{ TypeName }}Publisher extends Publisher, {{ java.FunctionType
|
||||
* @param value value
|
||||
*/
|
||||
void setDefault({{ java.ValueType }} value);
|
||||
|
||||
{% endif %}
|
||||
@Override
|
||||
default void accept({{ java.ValueType }} value) {
|
||||
set(value);
|
||||
|
||||
137
ntcore/src/test/java/edu/wpi/first/networktables/RawTest.java
Normal file
137
ntcore/src/test/java/edu/wpi/first/networktables/RawTest.java
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.networktables;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@SuppressWarnings("PMD.SimplifiableTestAssertion")
|
||||
class RawTest {
|
||||
private NetworkTableInstance m_inst;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
m_inst = NetworkTableInstance.create();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
m_inst.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGenericByteArray() {
|
||||
GenericEntry entry = m_inst.getTopic("test").getGenericEntry("raw");
|
||||
entry.setRaw(new byte[] {5}, 10);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {5}));
|
||||
entry.setRaw(new byte[] {5, 6, 7}, 1, 2, 15);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {6, 7}));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.setRaw(new byte[] {5}, -1, 2, 20));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.setRaw(new byte[] {5}, 1, -2, 20));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.setRaw(new byte[] {5}, 1, 1, 20));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRawByteArray() {
|
||||
RawEntry entry = m_inst.getRawTopic("test").getEntry("raw", new byte[] {});
|
||||
entry.set(new byte[] {5}, 10);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {5}));
|
||||
entry.set(new byte[] {5, 6, 7}, 1, 2, 15);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {6, 7}));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.set(new byte[] {5}, -1, 1, 20));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.set(new byte[] {5}, 1, -1, 20));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.set(new byte[] {5}, 1, 1, 20));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGenericByteBuffer() {
|
||||
GenericEntry entry = m_inst.getTopic("test").getGenericEntry("raw");
|
||||
entry.setRaw(ByteBuffer.wrap(new byte[] {5}), 10);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {5}));
|
||||
entry.setRaw(ByteBuffer.wrap(new byte[] {5, 6, 7}).position(1), 15);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {6, 7}));
|
||||
entry.setRaw(ByteBuffer.wrap(new byte[] {5, 6, 7}).position(1).limit(2), 16);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {6}));
|
||||
entry.setRaw(ByteBuffer.wrap(new byte[] {8, 9, 0}), 1, 2, 20);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {9, 0}));
|
||||
entry.setRaw(ByteBuffer.wrap(new byte[] {1, 2, 3}).position(2), 0, 2, 25);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {1, 2}));
|
||||
assertThrows(
|
||||
IndexOutOfBoundsException.class,
|
||||
() -> entry.setRaw(ByteBuffer.wrap(new byte[] {5}), -1, 1, 30));
|
||||
assertThrows(
|
||||
IndexOutOfBoundsException.class,
|
||||
() -> entry.setRaw(ByteBuffer.wrap(new byte[] {5}), 1, -1, 30));
|
||||
assertThrows(
|
||||
IndexOutOfBoundsException.class,
|
||||
() -> entry.setRaw(ByteBuffer.wrap(new byte[] {5}), 1, 1, 30));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRawByteBuffer() {
|
||||
RawEntry entry = m_inst.getRawTopic("test").getEntry("raw", new byte[] {});
|
||||
entry.set(ByteBuffer.wrap(new byte[] {5}), 10);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {5}));
|
||||
entry.set(ByteBuffer.wrap(new byte[] {5, 6, 7}).position(1), 15);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {6, 7}));
|
||||
entry.set(ByteBuffer.wrap(new byte[] {5, 6, 7}).position(1).limit(2), 16);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {6}));
|
||||
entry.set(ByteBuffer.wrap(new byte[] {8, 9, 0}), 1, 2, 20);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {9, 0}));
|
||||
entry.set(ByteBuffer.wrap(new byte[] {1, 2, 3}).position(2), 0, 2, 25);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {1, 2}));
|
||||
assertThrows(
|
||||
IndexOutOfBoundsException.class,
|
||||
() -> entry.set(ByteBuffer.wrap(new byte[] {5}), -1, 1, 30));
|
||||
assertThrows(
|
||||
IndexOutOfBoundsException.class,
|
||||
() -> entry.set(ByteBuffer.wrap(new byte[] {5}), 1, -1, 30));
|
||||
assertThrows(
|
||||
IndexOutOfBoundsException.class,
|
||||
() -> entry.set(ByteBuffer.wrap(new byte[] {5}), 1, 1, 30));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGenericNativeByteBuffer() {
|
||||
GenericEntry entry = m_inst.getTopic("test").getGenericEntry("raw");
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(3);
|
||||
bb.put(new byte[] {5, 6, 7});
|
||||
entry.setRaw(bb.position(1), 15);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {6, 7}));
|
||||
entry.setRaw(bb.limit(2), 16);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {6}));
|
||||
bb.clear();
|
||||
bb.put(new byte[] {8, 9, 0});
|
||||
entry.setRaw(bb, 1, 2, 20);
|
||||
assertTrue(Arrays.equals(entry.getRaw(new byte[] {}), new byte[] {9, 0}));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.setRaw(bb, -1, 1, 25));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.setRaw(bb, 1, -1, 25));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.setRaw(bb, 2, 2, 25));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRawNativeByteBuffer() {
|
||||
RawEntry entry = m_inst.getRawTopic("test").getEntry("raw", new byte[] {});
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(3);
|
||||
bb.put(new byte[] {5, 6, 7});
|
||||
entry.set(bb.position(1), 15);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {6, 7}));
|
||||
entry.set(bb.limit(2), 16);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {6}));
|
||||
bb.clear();
|
||||
bb.put(new byte[] {8, 9, 0});
|
||||
entry.set(bb, 1, 2, 20);
|
||||
assertTrue(Arrays.equals(entry.get(new byte[] {}), new byte[] {9, 0}));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.set(bb, -1, 1, 25));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.set(bb, 1, -1, 25));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> entry.set(bb, 2, 2, 25));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user