Files
allwpilib/datalog/src/main/java/org/wpilib/datalog/RawLogEntry.java
2025-11-07 23:09:21 -08:00

368 lines
11 KiB
Java

// 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 org.wpilib.datalog;
import java.nio.ByteBuffer;
import java.util.Arrays;
/** Log raw byte array values. */
public class RawLogEntry extends DataLogEntry {
/** The data type for raw values. */
public static final String kDataType = "raw";
/**
* Constructs a raw log entry.
*
* @param log datalog
* @param name name of the entry
* @param metadata metadata
* @param type Data type
* @param timestamp entry creation timestamp (0=now)
*/
public RawLogEntry(DataLog log, String name, String metadata, String type, long timestamp) {
super(log, name, type, metadata, timestamp);
}
/**
* Constructs a raw log entry.
*
* @param log datalog
* @param name name of the entry
* @param metadata metadata
* @param type Data type
*/
public RawLogEntry(DataLog log, String name, String metadata, String type) {
this(log, name, metadata, type, 0);
}
/**
* Constructs a raw log entry.
*
* @param log datalog
* @param name name of the entry
* @param metadata metadata
* @param timestamp entry creation timestamp (0=now)
*/
public RawLogEntry(DataLog log, String name, String metadata, long timestamp) {
this(log, name, metadata, kDataType, timestamp);
}
/**
* Constructs a raw log entry.
*
* @param log datalog
* @param name name of the entry
* @param metadata metadata
*/
public RawLogEntry(DataLog log, String name, String metadata) {
this(log, name, metadata, 0);
}
/**
* Constructs a raw log entry.
*
* @param log datalog
* @param name name of the entry
* @param timestamp entry creation timestamp (0=now)
*/
public RawLogEntry(DataLog log, String name, long timestamp) {
this(log, name, "", timestamp);
}
/**
* Constructs a raw log entry.
*
* @param log datalog
* @param name name of the entry
*/
public RawLogEntry(DataLog log, String name) {
this(log, name, 0);
}
/**
* Appends a record to the log.
*
* @param value Value to record; will send entire array contents
* @param timestamp Time stamp (0 to indicate now)
*/
public void append(byte[] value, long timestamp) {
m_log.appendRaw(m_entry, value, timestamp);
}
/**
* Appends a record to the log.
*
* @param value Value to record; will send entire array contents
*/
public void append(byte[] value) {
append(value, 0);
}
/**
* Appends a record to the log.
*
* @param value Data to record
* @param start Start position of data (in byte array)
* @param len Length of data (must be less than or equal to value.length - offset)
* @param timestamp Time stamp (0 to indicate now)
*/
public void append(byte[] value, int start, int len, long timestamp) {
m_log.appendRaw(m_entry, value, start, len, timestamp);
}
/**
* Appends a record to the log.
*
* @param value Data to record
* @param start Start position of data (in byte array)
* @param len Length of data (must be less than or equal to value.length - offset)
*/
public void append(byte[] value, int start, int len) {
append(value, start, len, 0);
}
/**
* Appends a record to the log.
*
* @param value Data to record; will send from value.position() to value.limit()
* @param timestamp Time stamp (0 to indicate now)
*/
public void append(ByteBuffer value, long timestamp) {
m_log.appendRaw(m_entry, value, timestamp);
}
/**
* Appends a record to the log.
*
* @param value Data to record; will send from value.position() to value.limit()
*/
public void append(ByteBuffer value) {
append(value, 0);
}
/**
* Appends a record to the log.
*
* @param value Data to record
* @param start Start position of data (in value buffer)
* @param len Length of data (must be less than or equal to value.length - offset)
* @param timestamp Time stamp (0 to indicate now)
*/
public void append(ByteBuffer value, int start, int len, long timestamp) {
m_log.appendRaw(m_entry, value, start, len, timestamp);
}
/**
* Appends a record to the log.
*
* @param value Data to record
* @param start Start position of data (in value buffer)
* @param len Length of data (must be less than or equal to value.length - offset)
*/
public void append(ByteBuffer value, int start, int len) {
append(value, start, len, 0);
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Value to record; will send entire array contents
* @param timestamp Time stamp (0 to indicate now)
*/
public synchronized void update(byte[] value, long timestamp) {
if (!equalsLast(value, 0, value.length)) {
copyToLast(value, 0, value.length);
append(value, timestamp);
}
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Value to record; will send entire array contents
*/
public void update(byte[] value) {
update(value, 0);
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Data to record
* @param start Start position of data (in byte array)
* @param len Length of data (must be less than or equal to value.length - offset)
* @param timestamp Time stamp (0 to indicate now)
*/
public synchronized void update(byte[] value, int start, int len, long timestamp) {
if (!equalsLast(value, start, len)) {
copyToLast(value, start, len);
append(value, start, len, timestamp);
}
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Data to record
* @param start Start position of data (in byte array)
* @param len Length of data (must be less than or equal to value.length - offset)
*/
public void update(byte[] value, int start, int len) {
update(value, start, len, 0);
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Data to record; will send from value.position() to value.limit()
* @param timestamp Time stamp (0 to indicate now)
*/
public synchronized void update(ByteBuffer value, long timestamp) {
if (!equalsLast(value)) {
int start = value.position();
int len = value.limit() - start;
copyToLast(value, start, len);
append(value, start, len, timestamp);
}
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Data to record; will send from value.position() to value.limit()
*/
public void update(ByteBuffer value) {
update(value, 0);
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Data to record
* @param start Start position of data (in value buffer)
* @param len Length of data (must be less than or equal to value.length - offset)
* @param timestamp Time stamp (0 to indicate now)
*/
public synchronized void update(ByteBuffer value, int start, int len, long timestamp) {
if (!equalsLast(value, start, len)) {
copyToLast(value, start, len);
append(value, start, len, timestamp);
}
}
/**
* Updates the last value and appends a record to the log if it has changed.
*
* <p>Note: the last value is local to this class instance; using update() with two instances
* pointing to the same underlying log entry name will likely result in unexpected results.
*
* @param value Data to record
* @param start Start position of data (in value buffer)
* @param len Length of data (must be less than or equal to value.length - offset)
*/
public void update(ByteBuffer value, int start, int len) {
update(value, start, len, 0);
}
/**
* Gets whether there is a last value.
*
* <p>Note: the last value is local to this class instance and updated only with update(), not
* append().
*
* @return True if last value exists, false otherwise.
*/
public synchronized boolean hasLastValue() {
return m_lastValue != null;
}
/**
* Gets the last value.
*
* <p>Note: the last value is local to this class instance and updated only with update(), not
* append().
*
* @return Last value, or null if none.
*/
@SuppressWarnings("PMD.ReturnEmptyCollectionRatherThanNull")
public synchronized byte[] getLastValue() {
if (m_lastValue == null) {
return null;
}
return Arrays.copyOf(m_lastValue.array(), m_lastValue.limit());
}
private boolean equalsLast(byte[] value, int start, int len) {
if (m_lastValue == null || m_lastValue.limit() != len) {
return false;
}
return Arrays.equals(m_lastValue.array(), 0, len, value, start, start + len);
}
@SuppressWarnings("PMD.SimplifyBooleanReturns")
private boolean equalsLast(ByteBuffer value) {
if (m_lastValue == null) {
return false;
}
return value.equals(m_lastValue);
}
private boolean equalsLast(ByteBuffer value, int start, int len) {
if (m_lastValue == null || m_lastValue.limit() != len) {
return false;
}
int origpos = value.position();
value.position(start);
int origlimit = value.limit();
value.limit(start + len);
boolean eq = value.equals(m_lastValue);
value.position(origpos);
value.limit(origlimit);
return eq;
}
private void copyToLast(byte[] value, int start, int len) {
if (m_lastValue == null || m_lastValue.limit() < len) {
m_lastValue = ByteBuffer.allocate(len);
}
System.arraycopy(value, start, m_lastValue.array(), 0, len);
m_lastValue.limit(len);
}
private void copyToLast(ByteBuffer value, int start, int len) {
if (m_lastValue == null || m_lastValue.limit() < len) {
m_lastValue = ByteBuffer.allocate(len);
}
int origpos = value.position();
value.position(start);
value.get(m_lastValue.array(), 0, len);
value.position(origpos);
m_lastValue.limit(len);
}
private ByteBuffer m_lastValue;
}