Class ByteBufferKaitaiStream

    • Constructor Detail

      • ByteBufferKaitaiStream

        public ByteBufferKaitaiStream​(String fileName)
                               throws IOException
        Initializes a stream, reading from a local file with specified fileName. Internally, FileChannel + MappedByteBuffer will be used.
        Parameters:
        fileName - file to read
        Throws:
        IOException - if file can't be read
      • ByteBufferKaitaiStream

        public ByteBufferKaitaiStream​(byte[] arr)
        Initializes a stream that will get data from the given array on read and put data into the array on write. Internally, a ByteBuffer is used to wrap the given array.
        Parameters:
        arr - byte array to read from or write to
      • ByteBufferKaitaiStream

        public ByteBufferKaitaiStream​(ByteBuffer buffer)
        Initializes a stream that will get data from given ByteBuffer on read and put data into it on write.
        Parameters:
        buffer - ByteBuffer to read from or write to
      • ByteBufferKaitaiStream

        public ByteBufferKaitaiStream​(long size)
        Initializes a stream that will write data into a fixed byte buffer in memory.
        Parameters:
        size - size of buffer in bytes
    • Method Detail

      • asRoBuffer

        public ByteBuffer asRoBuffer()
        Provide a read-only version of the ByteBuffer backing the data of this instance.

        This way one can access the underlying raw bytes associated with this structure, but it is important to note that the caller needs to know what this raw data is: Depending on the hierarchy of user types, how the format has been described and how a user type is actually used, it might be that one accesses all data of some format or only a special substream view of it. We can't know currently, so one needs to keep that in mind when authoring a KSY and e.g. use substreams with user types whenever such a type most likely needs to access its underlying raw data. Using a substream in KSY and directly passing some raw data to a user type outside of normal KS parse order is equivalent and will provide the same results. If no substream is used instead, the here provided data might differ depending on the context in which the associated type was parsed, because the underlying ByteBuffer might contain the data of all parent types and such as well and not only the one the caller is actually interested in.

        The returned ByteBuffer is always rewinded to position 0, because this stream was most likely used to parse a type already, in which case the former position would have been at the end of the buffer. Such a position doesn't help a common reading user much and that fact can easily be forgotten, repositioning to another index than the start is pretty easy as well. Rewinding/repositioning doesn't even harm performance in any way.

        Returns:
        read-only ByteBuffer to access raw data for the associated type.
      • close

        public void close()
                   throws IOException
        Closes the stream safely, writing the buffered bits to the underlying byte stream first (if applicable). If there was an open file associated with the stream, closes that file.

        If the last read/write/seek operation in the stream was KaitaiStream.writeBitsIntBe(int, long) or KaitaiStream.writeBitsIntLe(int, long) and the stream ended at an unaligned bit position (i.e. not at a byte boundary), writes a final byte with buffered bits to the underlying stream before closing the stream.

        Regardless of whether the closure is successful or not, always relinquishes the underlying resources. In accordance with Closeable.close(), subsequent calls have no effect. Once this method has been called, read and write operations, seeking or accessing the state using pos(), size() or isEof() on this stream will typically throw a NullPointerException.

        Specified by:
        close in interface AutoCloseable
        Specified by:
        close in interface Closeable
        Specified by:
        close in class KaitaiStream
        Implementation Note:

        Unfortunately, there is no simple way to close memory-mapped ByteBuffer in Java and unmap underlying file. As MappedByteBuffer documentation suggests, "mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected". Thus, the best we can do is to delete all references to it, which breaks all subsequent read.. methods with NullPointerException. Afterwards, a call to System.gc() will typically release the mmap, if garbage collection will be triggered.

        There is a JDK-4724038 request for adding unmap method filed at Java bugtracker since 2002, but as of 2018, it is still unresolved.

        A couple of unsafe approaches (such as using JNI, or using reflection to invoke JVM internal APIs) have been suggested and used with some success, but these are either unportable or dangerous (may crash JVM), so we're not using them in this general purpose code.

        For more examples and suggestions, see: How to unmap a file from memory mapped using FileChannel in java?

        Throws:
        IOException - if FileChannel can't be closed
      • isEof

        public boolean isEof()
        Description copied from class: KaitaiStream
        Check if stream pointer is at the end of stream.
        Specified by:
        isEof in class KaitaiStream
        Returns:
        true if we are located at the end of the stream
      • seek

        public void seek​(int newPos)
        Description copied from class: KaitaiStream
        Set stream pointer to designated position (int).
        Specified by:
        seek in class KaitaiStream
        Parameters:
        newPos - new position (offset in bytes from the beginning of the stream)
      • seek

        public void seek​(long newPos)
        Description copied from class: KaitaiStream
        Set stream pointer to designated position (long).
        Specified by:
        seek in class KaitaiStream
        Parameters:
        newPos - new position (offset in bytes from the beginning of the stream)
      • pos

        public int pos()
        Description copied from class: KaitaiStream
        Get current position of a stream pointer.
        Specified by:
        pos in class KaitaiStream
        Returns:
        pointer position, number of bytes from the beginning of the stream
      • size

        public long size()
        Description copied from class: KaitaiStream
        Get total size of the stream in bytes.
        Specified by:
        size in class KaitaiStream
        Returns:
        size of the stream in bytes
      • readS1

        public byte readS1()
        Reads one signed 1-byte integer, returning it properly as Java's "byte" type.
        Specified by:
        readS1 in class KaitaiStream
        Returns:
        1-byte integer read from a stream
      • readBytesNotAligned

        protected byte[] readBytesNotAligned​(long n)
        Description copied from class: KaitaiStream
        Internal method to read the specified number of bytes from the stream. Unlike KaitaiStream.readBytes(long), it doesn't align the bit position to the next byte boundary.
        Specified by:
        readBytesNotAligned in class KaitaiStream
        Parameters:
        n - number of bytes to read
        Returns:
        read bytes as a byte array
      • readBytesFull

        public byte[] readBytesFull()
        Reads all the remaining bytes in a stream as byte array.
        Specified by:
        readBytesFull in class KaitaiStream
        Returns:
        all remaining bytes in a stream as byte array
      • readBytesTerm

        public byte[] readBytesTerm​(byte term,
                                    boolean includeTerm,
                                    boolean consumeTerm,
                                    boolean eosError)
        Specified by:
        readBytesTerm in class KaitaiStream
      • substream

        public KaitaiStream substream​(long n)
        Description copied from class: KaitaiStream
        Reserves next `n` bytes from current stream as a KaitaiStream-compatible substream. Substream has its own pointer and addressing in the range of [0, n) bytes. This stream's pointer is advanced to the position right after this substream.
        Specified by:
        substream in class KaitaiStream
        Parameters:
        n - number of bytes to reserve for a substream
        Returns:
        substream covering n bytes from the current position
      • writeS1

        public void writeS1​(byte v)
        Writes one signed 1-byte integer.
        Specified by:
        writeS1 in class KaitaiStream
      • writeBytesNotAligned

        protected void writeBytesNotAligned​(byte[] buf)
        Description copied from class: KaitaiStream
        Internal method to write the given byte array to the stream. Unlike KaitaiStream.writeBytes(byte[]), it doesn't align the bit position to the next byte boundary.
        Specified by:
        writeBytesNotAligned in class KaitaiStream
        Parameters:
        buf - byte array to write