diff options
Diffstat (limited to 'Minecraft.World/ByteBuffer.cpp')
| -rw-r--r-- | Minecraft.World/ByteBuffer.cpp | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/Minecraft.World/ByteBuffer.cpp b/Minecraft.World/ByteBuffer.cpp new file mode 100644 index 00000000..66514737 --- /dev/null +++ b/Minecraft.World/ByteBuffer.cpp @@ -0,0 +1,478 @@ +#include "stdafx.h" + +#include "IntBuffer.h" +#include "FloatBuffer.h" +#include "ByteBuffer.h" + +ByteBuffer::ByteBuffer( unsigned int capacity ) : Buffer( capacity ) +{ + hasBackingArray = false; + buffer = new byte[capacity]; + memset( buffer,0,sizeof(byte)*capacity); + byteOrder = BIGENDIAN; +} + +//Allocates a new direct byte buffer. +//The new buffer's position will be zero, its limit will be its capacity, and its mark will be undefined. Whether or not it has a backing array is unspecified. +// +//Parameters: +//capacity - The new buffer's capacity, in bytes +//Returns: +//The new byte buffer +ByteBuffer *ByteBuffer::allocateDirect(int capacity) +{ + return new ByteBuffer(capacity); +} + + +ByteBuffer::ByteBuffer( unsigned int capacity, byte *backingArray ) : Buffer( capacity ) +{ + hasBackingArray = true; + buffer = backingArray; +} + +ByteBuffer::~ByteBuffer() +{ + if( !hasBackingArray ) + delete[] buffer; +} + +//Wraps a byte array into a buffer. +//The new buffer will be backed by the given byte array; that is, modifications to the buffer will cause the array +//to be modified and vice versa. The new buffer's capacity and limit will be array.length, its position will be zero, +//and its mark will be undefined. Its backing array will be the given array, and its array offset will be zero. +// +//Parameters: +//array - The array that will back this buffer +//Returns: +//The new byte buffer +ByteBuffer *ByteBuffer::wrap(byteArray &b) +{ + return new ByteBuffer( b.length, b.data ); +} + +//Allocates a new byte buffer. +//The new buffer's position will be zero, its limit will be its capacity, and its mark will be undefined. +//It will have a backing array, and its array offset will be zero. +// +//Parameters: +//capacity - The new buffer's capacity, in bytes +//Returns: +//The new byte buffer +ByteBuffer *ByteBuffer::allocate(unsigned int capacity) +{ + return new ByteBuffer( capacity ); +} + +//Modifies this buffer's byte order. +//Parameters: +//bo - The new byte order, either BIGENDIAN or LITTLEENDIAN +void ByteBuffer::order(ByteOrder bo) +{ + byteOrder = bo; +} + +//Flips this buffer. The limit is set to the current position and then the position is set to zero. +//If the mark is defined then it is discarded. +// +//Returns: +//This buffer +ByteBuffer *ByteBuffer::flip() +{ + m_limit = m_position; + m_position = 0; + return this; +} + +// 4J Added so we can write this to a file +byte *ByteBuffer::getBuffer() +{ + return buffer; +} + +int ByteBuffer::getSize() +{ + // TODO 4J Stu - Should this be the capcity and not the limit? + return m_limit; +} +// End 4J + +//Absolute get method. Reads the byte at the given index. +//Parameters: +//index - The index from which the byte will be read +//Returns: +//The byte at the given index +//Throws: +//IndexOutOfBoundsException - If index is negative or not smaller than the buffer's limit +BYTE ByteBuffer::get(int index) +{ + assert( index < m_limit ); + assert( index >= 0 ); + + return buffer[index]; +} + +//Relative get method for reading an int value. +//Reads the next four bytes at this buffer's current position, composing them into an int value according to the +//current byte order, and then increments the position by four. +// +//Returns: +//The int value at the buffer's current position +int ByteBuffer::getInt() +{ + assert( m_position+3 < m_limit ); + + int value = 0; + + int b1 = buffer[ m_position ]; + int b2 = buffer[ m_position+1 ]; + int b3 = buffer[ m_position+2 ]; + int b4 = buffer[ m_position+3 ]; + + m_position += 4; + + if( byteOrder == BIGENDIAN ) + { + value = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; + } + else if( byteOrder == LITTLEENDIAN ) + { + value = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + } + return value; +} + +//Absolute get method for reading an int value. +//Reads four bytes at the given index, composing them into a int value according to the current byte order. +// +//Parameters: +//index - The index from which the bytes will be read +//Returns: +//The int value at the given index +int ByteBuffer::getInt(unsigned int index) +{ + assert( index+3 < m_limit ); + int value = 0; + + int b1 = buffer[ index ]; + int b2 = buffer[ index+1 ]; + int b3 = buffer[ index+2 ]; + int b4 = buffer[ index+3 ]; + + if( byteOrder == BIGENDIAN ) + { + value = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; + } + else if( byteOrder == LITTLEENDIAN ) + { + value = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + } + return value; +} + +//Relative get method for reading a long value. +//Reads the next eight bytes at this buffer's current position, composing them into a long value according to the current byte order, +//and then increments the position by eight. +// +//Returns: +//The long value at the buffer's current position +__int64 ByteBuffer::getLong() +{ + assert( m_position+8 < m_limit ); + + __int64 value = 0; + + __int64 b1 = buffer[ m_position ]; + __int64 b2 = buffer[ m_position+1 ]; + __int64 b3 = buffer[ m_position+2 ]; + __int64 b4 = buffer[ m_position+3 ]; + __int64 b5 = buffer[ m_position+4 ]; + __int64 b6 = buffer[ m_position+5 ]; + __int64 b7 = buffer[ m_position+6 ]; + __int64 b8 = buffer[ m_position+7 ]; + + m_position += 8; + + if( byteOrder == BIGENDIAN ) + { + value = (b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) | (b5 << 24) | (b6 << 16) | (b7 << 8) | b8; + } + else if( byteOrder == LITTLEENDIAN ) + { + value = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); + } + return value; +} + +//Relative get method for reading a short value. +//Reads the next two bytes at this buffer's current position, composing them into a short value according to the current +//byte order, and then increments the position by two. +// +//Returns: +//The short value at the buffer's current position +short ByteBuffer::getShort() +{ + assert( m_position+1 < m_limit ); + + short value = 0; + + short b1 = buffer[ m_position ]; + short b2 = buffer[ m_position+1 ]; + + m_position += 2; + + if( byteOrder == BIGENDIAN ) + { + value = (b1 << 8) | b2; + } + else if( byteOrder == LITTLEENDIAN ) + { + value = b1 | (b2 << 8); + } + return value; +} + +void ByteBuffer::getShortArray(shortArray &s) +{ + // TODO 4J Stu - Should this function be writing from the start of the buffer, or from position? + // And should it update position? + assert( s.length >= m_limit/2 ); + + // 4J Stu - Assumes big endian + memcpy( s.data, buffer, (m_limit-m_position) ); +} + +//Absolute put method (optional operation). +//Writes the given byte into this buffer at the given index. +// +//Parameters: +//index - The index at which the byte will be written +//b - The byte value to be written +//Returns: +//This buffer +//Throws: +//IndexOutOfBoundsException - If index is negative or not smaller than the buffer's limit +//ReadOnlyBufferException - If this buffer is read-only +ByteBuffer *ByteBuffer::put(int index, byte b) +{ + assert( index < m_limit ); + assert( index >= 0 ); + + buffer[index] = b; + return this; +} + + +//Relative put method for writing an int value (optional operation). +//Writes four bytes containing the given int value, in the current byte order, into this buffer at the current position, +//and then increments the position by four. +// +//Parameters: +//value - The int value to be written +//Returns: +//This buffer +ByteBuffer *ByteBuffer::putInt(int value) +{ + assert( m_position+3 < m_limit ); + + if( byteOrder == BIGENDIAN ) + { + buffer[m_position] = (value >> 24) & 0xFF; + buffer[m_position+1] = (value >> 16) & 0xFF; + buffer[m_position+2] = (value >> 8) & 0xFF; + buffer[m_position+3] = value & 0xFF; + } + else if( byteOrder == LITTLEENDIAN ) + { + buffer[m_position] = value & 0xFF; + buffer[m_position+1] = (value >> 8) & 0xFF; + buffer[m_position+2] = (value >> 16) & 0xFF; + buffer[m_position+3] = (value >> 24) & 0xFF; + } + + m_position += 4; + + return this; +} + +//Absolute put method for writing an int value (optional operation). +//Writes four bytes containing the given int value, in the current byte order, into this buffer at the given index. +// +//Parameters: +//index - The index at which the bytes will be written +//value - The int value to be written +//Returns: +//This buffer +ByteBuffer *ByteBuffer::putInt(unsigned int index, int value) +{ + assert( index+3 < m_limit ); + + if( byteOrder == BIGENDIAN ) + { + buffer[index] = (value >> 24) & 0xFF; + buffer[index+1] = (value >> 16) & 0xFF; + buffer[index+2] = (value >> 8) & 0xFF; + buffer[index+3] = value & 0xFF; + } + else if( byteOrder == LITTLEENDIAN ) + { + buffer[index] = value & 0xFF; + buffer[index+1] = (value >> 8) & 0xFF; + buffer[index+2] = (value >> 16) & 0xFF; + buffer[index+3] = (value >> 24) & 0xFF; + } + + return this; +} + +//Relative put method for writing a short value (optional operation). +//Writes two bytes containing the given short value, in the current byte order, into this buffer at the current position, +//and then increments the position by two. +// +//Parameters: +//value - The short value to be written +//Returns: +//This buffer +ByteBuffer *ByteBuffer::putShort(short value) +{ + assert( m_position+1 < m_limit ); + + if( byteOrder == BIGENDIAN ) + { + buffer[m_position] = (value >> 8) & 0xFF; + buffer[m_position+1] = value & 0xFF; + } + else if( byteOrder == LITTLEENDIAN ) + { + buffer[m_position] = value & 0xFF; + buffer[m_position+1] = (value >> 8) & 0xFF; + } + + m_position += 2; + + return this; +} + +ByteBuffer *ByteBuffer::putShortArray(shortArray &s) +{ + // TODO 4J Stu - Should this function be writing from the start of the buffer, or from position? + // And should it update position? + assert( s.length*2 <= m_limit); + + // 4J Stu - Assumes big endian + memcpy( buffer, s.data, s.length*2 ); + + return this; +} + +//Relative put method for writing a long value (optional operation). +//Writes eight bytes containing the given long value, in the current byte order, into this buffer at the current position, +//and then increments the position by eight. +// +//Parameters: +//value - The long value to be written +//Returns: +//This buffer +ByteBuffer *ByteBuffer::putLong(__int64 value) +{ + assert( m_position+7 < m_limit ); + + if( byteOrder == BIGENDIAN ) + { + buffer[m_position] = (value >> 56) & 0xFF; + buffer[m_position+1] = (value >> 48) & 0xFF; + buffer[m_position+2] = (value >> 40) & 0xFF; + buffer[m_position+3] = (value >> 32) & 0xFF; + buffer[m_position+4] = (value >> 24) & 0xFF; + buffer[m_position+5] = (value >> 16) & 0xFF; + buffer[m_position+6] = (value >> 8) & 0xFF; + buffer[m_position+7] = value & 0xFF; + } + else if( byteOrder == LITTLEENDIAN ) + { + buffer[m_position] = value & 0xFF; + buffer[m_position+1] = (value >> 8) & 0xFF; + buffer[m_position+2] = (value >> 16) & 0xFF; + buffer[m_position+3] = (value >> 24) & 0xFF; + buffer[m_position+4] = (value >> 32) & 0xFF; + buffer[m_position+5] = (value >> 40) & 0xFF; + buffer[m_position+6] = (value >> 48) & 0xFF; + buffer[m_position+7] = (value >> 56) & 0xFF; + } + + return this; +} + +//Relative bulk put method (optional operation). +//This method transfers the entire content of the given source byte array into this buffer. +//An invocation of this method of the form dst.put(a) behaves in exactly the same way as the invocation +// +// dst.put(a, 0, a.length) +//Returns: +//This buffer +ByteBuffer *ByteBuffer::put(byteArray inputArray) +{ + if( inputArray.length > remaining() ) + assert( false ); //TODO 4J Stu - Some kind of exception? + + std::copy( inputArray.data, inputArray.data + inputArray.length, buffer+m_position ); + + m_position += inputArray.length; + + return this; +} + +byteArray ByteBuffer::array() +{ + return byteArray( buffer, m_capacity ); +} + +//Creates a view of this byte buffer as an int buffer. +//The content of the new buffer will start at this buffer's current position. Changes to this buffer's content +//will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. +// +//The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this buffer +//divided by four, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct, and +//it will be read-only if, and only if, this buffer is read-only. +// +//Returns: +//A new int buffer +IntBuffer *ByteBuffer::asIntBuffer() +{ + // TODO 4J Stu - Is it safe to just cast our byte array pointer to another type? + return new IntBuffer( (m_limit-m_position)/4, (int *) (buffer+m_position) ); +} + +//Creates a view of this byte buffer as a float buffer. +//The content of the new buffer will start at this buffer's current position. Changes to this buffer's content will be +//visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent. +// +//The new buffer's position will be zero, its capacity and its limit will be the number of bytes remaining in this buffer +//divided by four, and its mark will be undefined. The new buffer will be direct if, and only if, this buffer is direct, +//and it will be read-only if, and only if, this buffer is read-only. +// +//Returns: +//A new float buffer +FloatBuffer *ByteBuffer::asFloatBuffer() +{ + // TODO 4J Stu - Is it safe to just cast our byte array pointer to another type? + return new FloatBuffer( (m_limit-m_position)/4, (float *) (buffer+m_position) ); +} + + + +#ifdef __PS3__ +// we're using the RSX now to upload textures to vram, so we need th main ram textures allocated from io space +ByteBuffer_IO::ByteBuffer_IO( unsigned int capacity ) + : ByteBuffer(capacity, (byte*)RenderManager.allocIOMem(capacity, 64)) +{ + memset( buffer,0,sizeof(byte)*capacity); + byteOrder = BIGENDIAN; +} + +ByteBuffer_IO::~ByteBuffer_IO() +{ +// delete buffer; + RenderManager.freeIOMem(buffer); +} +#endif // __PS3__
\ No newline at end of file |
