ss: Introduce a safe byte buffer wrapper for use by custom state values
authorGeneviève Bastien <gbastien+lttng@versatic.net>
Tue, 10 May 2016 01:56:31 +0000 (21:56 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Tue, 17 May 2016 18:48:41 +0000 (14:48 -0400)
This byte buffer wrapper safely wraps a ByteBuffer inside a class that does not
allow to pass the limit or change the position so that custom state values can
safely write directly to it, without passing by byte arrays.

Change-Id: I428ee4406aa2a913d91ebc2c075bc92861286b3f
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/72359
Reviewed-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
Tested-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
Reviewed-by: Hudson CI
Reviewed-by: Alexandre Montplaisir <alexmonthy@efficios.com>
statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/statevalue/SafeByteBufferWrapperTest.java [new file with mode: 0644]
statesystem/org.eclipse.tracecompass.statesystem.core/META-INF/MANIFEST.MF
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/ISafeByteBufferReader.java [new file with mode: 0644]
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/ISafeByteBufferWriter.java [new file with mode: 0644]
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/SafeByteBufferFactory.java [new file with mode: 0644]
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/statevalue/SafeByteBufferWrapper.java [new file with mode: 0644]

diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/statevalue/SafeByteBufferWrapperTest.java b/statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/statevalue/SafeByteBufferWrapperTest.java
new file mode 100644 (file)
index 0000000..ec75013
--- /dev/null
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.statesystem.core.tests.statevalue;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+
+import org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue.ISafeByteBufferReader;
+import org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue.ISafeByteBufferWriter;
+import org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue.SafeByteBufferFactory;
+import org.eclipse.tracecompass.internal.statesystem.core.statevalue.SafeByteBufferWrapper;
+import org.junit.Test;
+
+/**
+ * Test for the {@link SafeByteBufferWrapper} class
+ *
+ * @author Geneviève Bastien
+ */
+public class SafeByteBufferWrapperTest {
+
+    private final ByteBuffer fMainBuffer;
+
+    /**
+     * Constructor. Prepares the main buffer and safe buffer
+     */
+    public SafeByteBufferWrapperTest() {
+        fMainBuffer = ByteBuffer.allocate(1024);
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#put(byte)}
+     * {@link SafeByteBufferWrapper#get()} methods
+     */
+    @Test
+    public void testReadWriteByte() {
+        byte val = Byte.MAX_VALUE;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.put(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.get());
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#put(byte[])}
+     * {@link SafeByteBufferWrapper#get(byte[])} methods
+     */
+    @Test
+    public void testReadWriteByteArray() {
+        byte[] val = { 0, 2, 1, 3 };
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.put(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        byte[] ret = new byte[4];
+        reader.get(ret);
+        assertArrayEquals(val, ret);
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#putChar(char)}
+     * {@link SafeByteBufferWrapper#getChar()} methods
+     */
+    @Test
+    public void testReadWriteChar() {
+        char val = 24;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putChar(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.getChar());
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#putDouble(double)}
+     * {@link SafeByteBufferWrapper#getDouble()} methods
+     */
+    @Test
+    public void testReadWriteDouble() {
+        double val = Double.MAX_VALUE;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putDouble(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.getDouble(), 10);
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#putFloat(float)}
+     * {@link SafeByteBufferWrapper#getFloat()} methods
+     */
+    @Test
+    public void testReadWriteFloat() {
+        float val = Float.MIN_VALUE;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putFloat(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.getFloat(), 10);
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#putInt(int)}
+     * {@link SafeByteBufferWrapper#getInt()} methods
+     */
+    @Test
+    public void testReadWriteInt() {
+        int val = Integer.MAX_VALUE;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putInt(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.getInt());
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#putLong(long)}
+     * {@link SafeByteBufferWrapper#getLong()} methods
+     */
+    @Test
+    public void testReadWriteLong() {
+        long val = Long.MIN_VALUE;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putLong(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.getLong());
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#putShort(short)}
+     * {@link SafeByteBufferWrapper#getShort()} methods
+     */
+    @Test
+    public void testReadWriteShort() {
+        short val = Short.MIN_VALUE;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putShort(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.getShort());
+    }
+
+    /**
+     * Test the {@link SafeByteBufferWrapper#putString(String)}
+     * {@link SafeByteBufferWrapper#getString()} methods
+     */
+    @Test
+    public void testReadWriteString() {
+        String val = "abcdefg";
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putString(val);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(val, reader.getString());
+    }
+
+    /**
+     * Test adding multiple values to the buffer, inside the limits
+     */
+    @Test
+    public void testMultipleValues() {
+        int valInt = 98;
+        short valShort = 34;
+        String valStr = "myString";
+        long valLong = 254238908543254L;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 512);
+        buffer.putInt(valInt);
+        buffer.putShort(valShort);
+        buffer.putString(valStr);
+        buffer.putLong(valLong);
+
+        // Reset the buffer and read it again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, 512);
+        assertEquals(valInt, reader.getInt());
+        assertEquals(valShort, reader.getShort());
+        assertEquals(valStr, reader.getString());
+        assertEquals(valLong, reader.getLong());
+    }
+
+    /**
+     * Test writing over the limit of the buffer
+     */
+    @Test(expected = BufferOverflowException.class)
+    public void testLimit() {
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, 5);
+        buffer.putDouble(Double.MIN_VALUE);
+    }
+
+    /**
+     * Test writing to main buffer after writing to safe buffer
+     */
+    @Test
+    public void testMainBuffer() {
+        String valString = "defghi";
+        long valLong = 54262542352L;
+        int valInt = 2048;
+        int bufferSize = Integer.BYTES + valString.length() + Long.BYTES;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, bufferSize);
+        buffer.putString(valString);
+        buffer.putLong(valLong);
+        fMainBuffer.putInt(valInt);
+
+        // Flip the main buffer to read again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, bufferSize);
+        assertEquals(valString, reader.getString());
+        assertEquals(valLong, reader.getLong());
+        assertEquals(valInt, fMainBuffer.getInt());
+    }
+
+    /**
+     * Test writing to main buffer after writing to safe buffer but not
+     * completely
+     */
+    @Test
+    public void testMainBuffer2() {
+        String valString = "defghi";
+        long valLong = 54262542352L;
+        int valInt = 2048;
+        int bufferSize = Integer.BYTES + valString.length() + Long.BYTES + Long.BYTES;
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, bufferSize);
+        buffer.putString(valString);
+        buffer.putLong(valLong);
+
+        // Assert the main buffer's position is after the safe buffer, even
+        // though it is not completely written
+        assertEquals(bufferSize, fMainBuffer.position());
+        fMainBuffer.putInt(valInt);
+
+        // Write the extra long at the end of the safe buffer
+        buffer.putLong(valLong);
+
+        // Start reading again
+        fMainBuffer.flip();
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, bufferSize);
+        assertEquals(valString, reader.getString());
+        assertEquals(valLong, reader.getLong());
+        assertEquals(valLong, reader.getLong());
+        assertEquals(valInt, fMainBuffer.getInt());
+    }
+
+    /**
+     * Test writing to main buffer before writing to safe buffer
+     */
+    @Test
+    public void testMainBuffer3() {
+        String valString = "defghi";
+        long valLong = 54262542352L;
+        int valInt = 2048;
+        int bufferSize = Integer.BYTES + valString.length() + Long.BYTES;
+
+        fMainBuffer.putLong(valLong);
+        fMainBuffer.putInt(valInt);
+
+        ISafeByteBufferWriter buffer = SafeByteBufferFactory.wrapWriter(fMainBuffer, bufferSize);
+        buffer.putString(valString);
+        buffer.putLong(valLong);
+
+        fMainBuffer.flip();
+        assertEquals(valLong, fMainBuffer.getLong());
+        assertEquals(valInt, fMainBuffer.getInt());
+
+        // Flip the main buffer
+        ISafeByteBufferReader reader = SafeByteBufferFactory.wrapReader(fMainBuffer, bufferSize);
+        assertEquals(valString, reader.getString());
+        assertEquals(valLong, reader.getLong());
+    }
+
+}
index e7b64818264e83a9b9a76e4fa0bd0ae23d430949..c9be6f07bb7427a13dd21ea8794d2be0e18c2836 100644 (file)
@@ -11,9 +11,11 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.core.resources,
  org.eclipse.tracecompass.common.core
-Export-Package: org.eclipse.tracecompass.internal.statesystem.core;x-friends:="org.eclipse.tracecompass.statesystem.core.tests",
+Export-Package: org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue;x-friends:="org.eclipse.tracecompass.statesystem.core.tests",
+ org.eclipse.tracecompass.internal.statesystem.core;x-friends:="org.eclipse.tracecompass.statesystem.core.tests",
  org.eclipse.tracecompass.internal.statesystem.core.backend;x-internal:=true,
  org.eclipse.tracecompass.internal.statesystem.core.backend.historytree;x-friends:="org.eclipse.tracecompass.statesystem.core.tests",
+ org.eclipse.tracecompass.internal.statesystem.core.statevalue;x-friends:="org.eclipse.tracecompass.statesystem.core.tests",
  org.eclipse.tracecompass.statesystem.core,
  org.eclipse.tracecompass.statesystem.core.backend,
  org.eclipse.tracecompass.statesystem.core.exceptions,
diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/ISafeByteBufferReader.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/ISafeByteBufferReader.java
new file mode 100644 (file)
index 0000000..29d0f79
--- /dev/null
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue;
+
+/**
+ * Interface for a safe ByteBuffer for reading purposes. This interface allows
+ * only to read data from a buffer, no other operation is allowed on it. The
+ * implementations must make sure that only the allowed data can be read.
+ *
+ * @author Geneviève Bastien
+ */
+public interface ISafeByteBufferReader {
+
+    /**
+     * Reads a byte at the buffer's current position
+     *
+     * @return The byte read
+     */
+    byte get();
+
+    /**
+     * Transfers bytes from this buffer's current position into the destination
+     * array
+     *
+     * @param dst
+     *            The destination array
+     */
+    void get(byte[] dst);
+
+    /**
+     * Reads the char at the buffer's current position
+     *
+     * @return The char read
+     */
+    char getChar();
+
+    /**
+     * Reads the double at the buffer's current position
+     *
+     * @return The double read
+     */
+    double getDouble();
+
+    /**
+     * Reads the float at the buffer's current position
+     *
+     * @return The float read
+     */
+    float getFloat();
+
+    /**
+     * Reads the int at the buffer's current position
+     *
+     * @return The int read
+     */
+    int getInt();
+
+    /**
+     * Reads the long at the buffer's current position
+     *
+     * @return The long read
+     */
+    long getLong();
+
+    /**
+     * Reads the short at the buffer's current position
+     *
+     * @return The short read
+     */
+    short getShort();
+
+    /**
+     * Gets a string from the byte buffer.
+     *
+     * @return The string value read
+     */
+    String getString();
+
+}
diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/ISafeByteBufferWriter.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/ISafeByteBufferWriter.java
new file mode 100644 (file)
index 0000000..f50f288
--- /dev/null
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue;
+
+/**
+ * Interface for a safe ByteBuffer for writing purposes. This interface allows
+ * only to write data from a buffer, no other operation is allowed on it. The
+ * implementation needs to make sure that the buffer does not write over the
+ * limits of the buffer.
+ *
+ * @author Geneviève Bastien
+ */
+public interface ISafeByteBufferWriter {
+
+    /**
+     * Writes a byte at the buffer's current position
+     *
+     * @param value
+     *            The byte to write
+     */
+    void put(byte value);
+
+    /**
+     * Transfers the bytes from the src array in the buffer at the current
+     * position
+     *
+     * @param src
+     *            the byte array to write
+     */
+    void put(byte[] src);
+
+    /**
+     * Writes a char at the buffer's current position
+     *
+     * @param value
+     *            The char to write
+     */
+    void putChar(char value);
+
+    /**
+     * Writes a double at the buffer's current position
+     *
+     * @param value
+     *            The double to write
+     */
+    void putDouble(double value);
+
+    /**
+     * Writes a float at the buffer's current position
+     *
+     * @param value
+     *            The float to write
+     */
+    void putFloat(float value);
+
+    /**
+     * Writes an int at the buffer's current position
+     *
+     * @param value
+     *            The int to write
+     */
+    void putInt(int value);
+
+    /**
+     * Writes a long at the buffer's current position
+     *
+     * @param value
+     *            The long to write
+     */
+    void putLong(long value);
+
+    /**
+     * Writes a short at the buffer's current position
+     *
+     * @param value
+     *            The short to write
+     */
+    void putShort(short value);
+
+    /**
+     * Writes a string value in the byte buffer. The implementation can decide
+     * what format it will use. They can also have a maximum size, in which case
+     * string should be truncated if they are larger than that.
+     *
+     * @param value
+     *            The String value to write to the buffer
+     */
+    void putString(String value);
+
+}
diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/SafeByteBufferFactory.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/provisional/statesystem/core/statevalue/SafeByteBufferFactory.java
new file mode 100644 (file)
index 0000000..86122a5
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue;
+
+import java.nio.ByteBuffer;
+
+import org.eclipse.tracecompass.internal.statesystem.core.statevalue.SafeByteBufferWrapper;
+
+/**
+ * Class that creates instances of safe byte buffers wrappers from a part of a
+ * ByteBuffer instance
+ *
+ * @author Geneviève Bastien
+ */
+public final class SafeByteBufferFactory {
+
+    private SafeByteBufferFactory() {
+
+    }
+
+    /**
+     * Creates a new safe byte buffer reader from the ByteBuffer's current
+     * position with a size limited to 'size'.
+     *
+     * @param buffer
+     *            The big ByteBuffer to safely wrap for reading
+     * @param size
+     *            The size of the new sub-buffer
+     * @return The safe byte buffer reader instance
+     */
+    public static ISafeByteBufferReader wrapReader(ByteBuffer buffer, int size) {
+        int pos = buffer.position();
+        // Slice the main buffer, so that position 0 is the current position
+        // set it as read-only also
+        ByteBuffer readOnlyBuffer = buffer.slice().asReadOnlyBuffer();
+        // Set its limit to the request limit
+        readOnlyBuffer.limit(size);
+        // Operations on fBuffer will not affect the main buffer's position, so
+        // we set its position to after the limit
+        buffer.position(pos + size);
+        return new SafeByteBufferWrapper(readOnlyBuffer);
+    }
+
+    /**
+     * Creates a new safe byte buffer writer from the ByteBuffer's current
+     * position with a size limited to 'size'.
+     *
+     * @param buffer
+     *            The big ByteBuffer to safely wrap for reading
+     * @param size
+     *            The size of the new sub-buffer
+     * @return The safe byte buffer writer instance
+     */
+    public static ISafeByteBufferWriter wrapWriter(ByteBuffer buffer, int size) {
+        int pos = buffer.position();
+        // Slice the main buffer, so that position 0 is the current position
+        ByteBuffer readWriteBuffer = buffer.slice();
+        // Set its limit to the request limit
+        readWriteBuffer.limit(size);
+        // Operations on fBuffer will not affect the main buffer's position, so
+        // we set its position to after the limit
+        buffer.position(pos + size);
+        return new SafeByteBufferWrapper(readWriteBuffer);
+    }
+
+    /**
+     * Get the serialized of a string object if it uses the
+     * {@link ISafeByteBufferWriter#putString(String)} method
+     *
+     * @param string
+     *            The string to write to the buffer
+     * @return The size of the string serialized by the
+     *         {@link ISafeByteBufferWriter#putString(String)} method, or -1 if
+     *         the string cannot be serialized
+     */
+    public static int getStringSizeInBuffer(String string) {
+        return SafeByteBufferWrapper.getStringSizeInBuffer(string);
+    }
+
+}
diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/statevalue/SafeByteBufferWrapper.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/statevalue/SafeByteBufferWrapper.java
new file mode 100644 (file)
index 0000000..c642f40
--- /dev/null
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.statesystem.core.statevalue;
+
+import java.nio.ByteBuffer;
+
+import org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue.ISafeByteBufferReader;
+import org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue.ISafeByteBufferWriter;
+
+/**
+ * This class is a wrapper around a ByteBuffer. The size to read/write to the
+ * buffer must be known from the beginning. It will not overflow onto the main
+ * buffer.
+ *
+ * This class may be used to wrap a small part of a bigger ByteBuffer in such a
+ * way that it limits the number of bytes to read/write. It will not overflow
+ * over or below the allowed positions in the big ByteBuffer while not requiring
+ * extra copies of byte arrays.
+ *
+ * This allows sequential read and write operations but does not allow resizes or
+ * seeks.
+ *
+ * @author Geneviève Bastien
+ * @since 2.0
+ */
+public class SafeByteBufferWrapper implements ISafeByteBufferReader, ISafeByteBufferWriter {
+
+    private final ByteBuffer fBuffer;
+
+    /**
+     * Constructor.
+     *
+     * @param buffer
+     *            The big ByteBuffer to safely wrap
+     */
+    public SafeByteBufferWrapper(ByteBuffer buffer) {
+        fBuffer = buffer;
+    }
+
+    @Override
+    public byte get() {
+        return fBuffer.get();
+    }
+
+    @Override
+    public void get(byte[] dst) {
+        fBuffer.get(dst);
+    }
+
+    @Override
+    public char getChar() {
+        return fBuffer.getChar();
+    }
+
+    @Override
+    public double getDouble() {
+        return fBuffer.getDouble();
+    }
+
+    @Override
+    public float getFloat() {
+        return fBuffer.getFloat();
+    }
+
+    @Override
+    public int getInt() {
+        return fBuffer.getInt();
+    }
+
+    @Override
+    public long getLong() {
+        return fBuffer.getLong();
+    }
+
+    @Override
+    public short getShort() {
+        return fBuffer.getShort();
+    }
+
+    @Override
+    public String getString() {
+        int strSize = fBuffer.getShort();
+        byte[] array = new byte[strSize];
+        fBuffer.get(array);
+        return new String(array);
+    }
+
+    @Override
+    public void put(byte value) {
+        fBuffer.put(value);
+    }
+
+    @Override
+    public void put(byte[] src) {
+        fBuffer.put(src);
+    }
+
+    @Override
+    public void putChar(char value) {
+        fBuffer.putChar(value);
+    }
+
+    @Override
+    public void putDouble(double value) {
+        fBuffer.putDouble(value);
+    }
+
+    @Override
+    public void putFloat(float value) {
+        fBuffer.putFloat(value);
+    }
+
+    @Override
+    public void putInt(int value) {
+        fBuffer.putInt(value);
+    }
+
+    @Override
+    public void putLong(long value) {
+        fBuffer.putLong(value);
+    }
+
+    @Override
+    public void putShort(short value) {
+        fBuffer.putShort(value);
+    }
+
+    @Override
+    public void putString(String value) {
+        String toWrite = value;
+        if (value.length() > Short.MAX_VALUE) {
+            toWrite = toWrite.substring(0, Short.MAX_VALUE);
+        }
+        fBuffer.putShort((short) value.length());
+        fBuffer.put(toWrite.getBytes());
+    }
+
+    /**
+     * Return the serialized size of the string in this byte buffer. The maximum
+     * size is {@link Short#MAX_VALUE}. A string with larger size will be
+     * truncated.
+     *
+     * @param string
+     *            The string to serialize
+     * @return The size of the serialized string
+     */
+    public static int getStringSizeInBuffer(String string) {
+        return Short.BYTES + Math.min(Short.MAX_VALUE, string.length());
+    }
+
+}
This page took 0.035138 seconds and 5 git commands to generate.