summaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/common/ec/EC_Data.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cz/crcs/ectester/common/ec/EC_Data.java')
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Data.java217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/cz/crcs/ectester/common/ec/EC_Data.java b/src/cz/crcs/ectester/common/ec/EC_Data.java
new file mode 100644
index 0000000..c048ef7
--- /dev/null
+++ b/src/cz/crcs/ectester/common/ec/EC_Data.java
@@ -0,0 +1,217 @@
+package cz.crcs.ectester.common.ec;
+
+import cz.crcs.ectester.common.util.ByteUtil;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * A list of byte arrays for holding EC data.
+ * <p>
+ * The data can be read from a byte array via <code>readBytes()</code>, from a CSV via <code>readCSV()</code>.
+ * The data can be exported to a byte array via <code>flatten()</code> or to a string array via <code>expand()</code>.
+ *
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public abstract class EC_Data {
+ String id;
+ int count;
+ byte[][] data;
+
+ private static final Pattern HEX = Pattern.compile("(0x|0X)?[a-fA-F\\d]+");
+
+ EC_Data() {
+ }
+
+ EC_Data(int count) {
+ this.count = count;
+ this.data = new byte[count][];
+ }
+
+ EC_Data(byte[][] data) {
+ this.count = data.length;
+ this.data = data;
+ }
+
+ EC_Data(String id, int count) {
+ this(count);
+ this.id = id;
+ }
+
+ EC_Data(String id, byte[][] data) {
+ this(data);
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public byte[][] getData() {
+ return data;
+ }
+
+ public byte[] getData(int index) {
+ return data[index];
+ }
+
+ public boolean hasData() {
+ return data != null;
+ }
+
+ public byte[] flatten() {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ for (byte[] param : data) {
+ byte[] length = new byte[2];
+ ByteUtil.setShort(length, 0, (short) param.length);
+
+ out.write(length, 0, 2);
+ out.write(param, 0, param.length);
+ }
+
+ return out.toByteArray();
+ }
+
+ public String[] expand() {
+ List<String> out = new ArrayList<>(count);
+ for (byte[] param : data) {
+ out.add(ByteUtil.bytesToHex(param, false));
+ }
+
+ return out.toArray(new String[out.size()]);
+ }
+
+ private static byte[] pad(byte[] data) {
+ if (data.length == 1) {
+ return new byte[]{(byte) 0, data[0]};
+ } else if (data.length == 0 || data.length > 2) {
+ return data;
+ }
+ return null;
+ }
+
+ private static byte[] parse(String param) {
+ byte[] data;
+ if (param.startsWith("0x") || param.startsWith("0X")) {
+ data = ByteUtil.hexToBytes(param.substring(2));
+ } else {
+ data = ByteUtil.hexToBytes(param);
+ }
+ if (data == null)
+ return new byte[0];
+ if (data.length < 2)
+ return pad(data);
+ return data;
+ }
+
+ private boolean readHex(String[] hex) {
+ if (hex.length != count) {
+ return false;
+ }
+
+ for (int i = 0; i < count; ++i) {
+ this.data[i] = parse(hex[i]);
+ }
+ return true;
+ }
+
+ public boolean readCSV(InputStream in) {
+ Scanner s = new Scanner(in);
+
+ s.useDelimiter(",|;");
+ List<String> data = new LinkedList<>();
+ while (s.hasNext()) {
+ String field = s.next();
+ data.add(field.replaceAll("\\s+", ""));
+ }
+
+ if (data.isEmpty()) {
+ return false;
+ }
+ for (String param : data) {
+ if (!HEX.matcher(param).matches()) {
+ return false;
+ }
+ }
+ return readHex(data.toArray(new String[data.size()]));
+ }
+
+ public boolean readBytes(byte[] bytes) {
+ if (bytes == null) {
+ return false;
+ }
+
+ int offset = 0;
+ for (int i = 0; i < count; i++) {
+ if (bytes.length - offset < 2) {
+ return false;
+ }
+ short paramLength = ByteUtil.getShort(bytes, offset);
+ offset += 2;
+ if (bytes.length < offset + paramLength) {
+ return false;
+ }
+ data[i] = new byte[paramLength];
+ System.arraycopy(bytes, offset, data[i], 0, paramLength);
+ offset += paramLength;
+ }
+ return true;
+ }
+
+ public boolean readByteArray(byte[][] bytes) {
+ if (bytes == null || count != bytes.length) {
+ return false;
+ }
+
+ for (int i = 0; i < count; ++i) {
+ data[i] = new byte[bytes[i].length];
+ System.arraycopy(bytes[i], 0, data[i], 0, bytes[i].length);
+ }
+ return true;
+ }
+
+ public void writeCSV(OutputStream out) throws IOException {
+ Writer w = new OutputStreamWriter(out);
+ w.write(String.join(",", expand()));
+ w.flush();
+ }
+
+ @Override
+ public String toString() {
+ return String.join(",", expand());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof EC_Data) {
+ EC_Data other = (EC_Data) obj;
+ if (this.id != null || other.id != null) {
+ return Objects.equals(this.id, other.id);
+ }
+
+ if (this.count != other.count)
+ return false;
+ for (int i = 0; i < this.count; ++i) {
+ if (!Arrays.equals(this.data[i], other.data[i])) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ if (this.id != null) {
+ return this.id.hashCode();
+ }
+ return Arrays.deepHashCode(this.data);
+ }
+}