mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/4jcraft.git
synced 2026-06-22 05:45:43 +00:00
restructure codebase according to vcproj filters
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "BufferedOutputStream.h"
|
||||
|
||||
// Creates a new buffered output stream to write data to the specified
|
||||
// underlying output stream with the specified buffer size. Parameters: out -
|
||||
// the underlying output stream. size - the buffer size.
|
||||
BufferedOutputStream::BufferedOutputStream(OutputStream* out, int size) {
|
||||
stream = out;
|
||||
buf = byteArray(size);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
BufferedOutputStream::~BufferedOutputStream() {
|
||||
// 4jcraft, changed to [], deallocates internal buffer
|
||||
// TODO: ArrayWithLength.h doesnt have a destructor.
|
||||
// this wouldnt need to be done manually.
|
||||
// but for some reason the destructor is commented out in the source code?
|
||||
delete[] buf.data;
|
||||
}
|
||||
|
||||
// Flushes this buffered output stream. This forces any buffered output bytes to
|
||||
// be written out to the underlying output stream.
|
||||
void BufferedOutputStream::flush() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"BufferedOutputStream::flush() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
stream->write(buf, 0, count);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Closes this output stream and releases any system resources associated with
|
||||
// the stream. The close method of FilterOutputStream calls its flush method,
|
||||
// and then calls the close method of its underlying output stream.
|
||||
void BufferedOutputStream::close() {
|
||||
flush();
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"BufferedOutputStream::close() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->close();
|
||||
}
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to this
|
||||
// buffered output stream. Ordinarily this method stores bytes from the given
|
||||
// array into this stream's buffer, flushing the buffer to the underlying output
|
||||
// stream as needed. If the requested length is at least as large as this
|
||||
// stream's buffer, however, then this method will flush the buffer and write
|
||||
// the bytes directly to the underlying output stream. Thus redundant
|
||||
// BufferedOutputStreams will not copy data unnecessarily.
|
||||
//
|
||||
// Overrides:
|
||||
// write in class FilterOutputStream
|
||||
// Parameters:
|
||||
// b - the data.
|
||||
// off - the start offset in the data.
|
||||
// len - the number of bytes to write.
|
||||
void BufferedOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
// Over the length of what we can store in our buffer - just flush the
|
||||
// buffer and output directly
|
||||
if (length >= buf.length) {
|
||||
flush();
|
||||
stream->write(b, offset, length);
|
||||
} else {
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
write(static_cast<unsigned int>(b[offset + i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Writes b.length bytes to this output stream.
|
||||
// The write method of FilterOutputStream calls its write method of three
|
||||
// arguments with the arguments b, 0, and b.length.
|
||||
//
|
||||
// Note that this method does not call the one-argument write method of its
|
||||
// underlying stream with the single argument b.
|
||||
void BufferedOutputStream::write(byteArray b) { write(b, 0, b.length); }
|
||||
|
||||
// Writes the specified byte to this buffered output stream.
|
||||
// Overrides:
|
||||
// write in class FilterOutputStream
|
||||
// Parameters:
|
||||
// b - the byte to be written.
|
||||
void BufferedOutputStream::write(unsigned int b) {
|
||||
buf[count++] = (uint8_t)b;
|
||||
if (count == buf.length) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "OutputStream.h"
|
||||
|
||||
class BufferedOutputStream : public OutputStream {
|
||||
private:
|
||||
OutputStream* stream;
|
||||
|
||||
protected:
|
||||
byteArray buf; // The internal buffer where data is stored.
|
||||
unsigned int count; // The number of valid bytes in the buffer.
|
||||
|
||||
public:
|
||||
BufferedOutputStream(OutputStream* out, int size);
|
||||
~BufferedOutputStream();
|
||||
|
||||
virtual void flush();
|
||||
virtual void close();
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(unsigned int b);
|
||||
};
|
||||
@@ -0,0 +1,160 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "BufferedReader.h"
|
||||
|
||||
// Creates a buffering character-input stream that uses a default-sized input
|
||||
// buffer. Parameters: in - A Reader
|
||||
BufferedReader::BufferedReader(Reader* in)
|
||||
: reader(in), readMark(0), bufferedMark(0), eofReached(false) {
|
||||
bufferSize = 64;
|
||||
buffer = new wchar_t[bufferSize];
|
||||
memset(buffer, 0, sizeof(wchar_t) * bufferSize);
|
||||
bufferMore();
|
||||
}
|
||||
|
||||
BufferedReader::~BufferedReader() { delete[] buffer; }
|
||||
|
||||
void BufferedReader::bufferMore() {
|
||||
// Don't buffer more unless we are going to read at least twice as much as
|
||||
// what is already left
|
||||
if (bufferedMark - readMark > (BUFFER_MORE_AMOUNT / 2)) return;
|
||||
|
||||
if (bufferSize < (bufferedMark + BUFFER_MORE_AMOUNT)) {
|
||||
// Enlarge the buffer
|
||||
wchar_t* temp = new wchar_t[bufferSize * 2];
|
||||
memset(temp, 0, sizeof(wchar_t) * bufferSize * 2);
|
||||
std::copy(buffer, buffer + bufferSize, temp);
|
||||
|
||||
delete[] buffer;
|
||||
buffer = temp;
|
||||
bufferSize = bufferSize * 2;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
unsigned int newCharsBuffered = 0;
|
||||
while (newCharsBuffered < BUFFER_MORE_AMOUNT &&
|
||||
(value = reader->read()) != -1) {
|
||||
buffer[bufferedMark++] = value;
|
||||
newCharsBuffered++;
|
||||
}
|
||||
}
|
||||
|
||||
// Closes the stream and releases any system resources associated with it. Once
|
||||
// the stream has been closed, further read(), ready(), mark(), reset(), or
|
||||
// skip() invocations will throw an IOException. Closing a previously closed
|
||||
// stream has no effect.
|
||||
void BufferedReader::close() { reader->close(); }
|
||||
|
||||
// Reads a single character.
|
||||
// Returns:
|
||||
// The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or
|
||||
// -1 if the end of the stream has been reached
|
||||
int BufferedReader::read() {
|
||||
// We should have buffered at least as much as we have read
|
||||
assert(bufferedMark >= readMark);
|
||||
|
||||
if (bufferedMark == readMark) {
|
||||
int value = reader->read();
|
||||
if (value == -1) return -1;
|
||||
|
||||
buffer[bufferedMark++] = value;
|
||||
|
||||
bufferMore();
|
||||
}
|
||||
|
||||
return buffer[readMark++];
|
||||
}
|
||||
|
||||
// Reads characters into a portion of an array.
|
||||
// This method implements the general contract of the corresponding read method
|
||||
// of the Reader class. As an additional convenience, it attempts to read as
|
||||
// many characters as possible by repeatedly invoking the read method of the
|
||||
// underlying stream. This iterated read continues until one of the following
|
||||
// conditions becomes true:
|
||||
//
|
||||
// The specified number of characters have been read,
|
||||
// The read method of the underlying stream returns -1, indicating end-of-file,
|
||||
// or The ready method of the underlying stream returns false, indicating that
|
||||
// further input requests would block. If the first read on the underlying
|
||||
// stream returns -1 to indicate end-of-file then this method returns -1.
|
||||
// Otherwise this method returns the number of characters actually read.
|
||||
// Subclasses of this class are encouraged, but not required, to attempt to read
|
||||
// as many characters as possible in the same fashion.
|
||||
//
|
||||
// Ordinarily this method takes characters from this stream's character buffer,
|
||||
// filling it from the underlying stream as necessary. If, however, the buffer
|
||||
// is empty, the mark is not valid, and the requested length is at least as
|
||||
// large as the buffer, then this method will read characters directly from the
|
||||
// underlying stream into the given array. Thus redundant BufferedReaders will
|
||||
// not copy data unnecessarily.
|
||||
//
|
||||
// Parameters:
|
||||
// cbuf - Destination buffer
|
||||
// off - Offset at which to start storing characters
|
||||
// len - Maximum number of characters to read
|
||||
// Returns:
|
||||
// The number of characters read, or -1 if the end of the stream has been
|
||||
// reached
|
||||
int BufferedReader::read(wchar_t cbuf[], unsigned int off, unsigned int len) {
|
||||
if (bufferSize < (bufferedMark + len)) {
|
||||
// Enlarge the buffer
|
||||
wchar_t* temp = new wchar_t[bufferSize * 2];
|
||||
memset(temp, 0, sizeof(wchar_t) * bufferSize * 2);
|
||||
std::copy(buffer, buffer + bufferSize, temp);
|
||||
|
||||
delete[] buffer;
|
||||
buffer = temp;
|
||||
bufferSize = bufferSize * 2;
|
||||
}
|
||||
|
||||
unsigned int charsRead = 0;
|
||||
while (charsRead < len && readMark <= bufferedMark) {
|
||||
cbuf[off + charsRead] = buffer[readMark++];
|
||||
charsRead++;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
while (charsRead < len && (value = reader->read()) != -1) {
|
||||
buffer[bufferedMark++] = value;
|
||||
cbuf[off + charsRead] = value;
|
||||
charsRead++;
|
||||
readMark++;
|
||||
}
|
||||
|
||||
bufferMore();
|
||||
|
||||
return charsRead;
|
||||
}
|
||||
|
||||
// Reads a line of text. A line is considered to be terminated by any one of a
|
||||
// line feed ('\n'), a carriage return ('\r'), or a carriage return followed
|
||||
// immediately by a linefeed. Returns: A String containing the contents of the
|
||||
// line, not including any line-termination characters, or null if the end of
|
||||
// the stream has been reached
|
||||
std::wstring BufferedReader::readLine() {
|
||||
std::wstring output = L"";
|
||||
bool newLineCharFound = false;
|
||||
|
||||
while (readMark < bufferedMark) {
|
||||
wchar_t value = buffer[readMark++];
|
||||
|
||||
if (!newLineCharFound) {
|
||||
if ((value == '\n') || (value == '\r')) {
|
||||
newLineCharFound = true;
|
||||
} else {
|
||||
output.push_back(value);
|
||||
}
|
||||
} else {
|
||||
if ((value != '\n') && (value != '\r')) {
|
||||
readMark--; // Move back the read mark on char so we get this
|
||||
// char again next time
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This will only actually read more from the stream if we have less
|
||||
// than half of the amount that will be added left to read
|
||||
bufferMore();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
class BufferedReader : public Reader {
|
||||
private:
|
||||
Reader* reader;
|
||||
wchar_t* buffer;
|
||||
|
||||
unsigned int readMark;
|
||||
unsigned int bufferedMark;
|
||||
unsigned int bufferSize;
|
||||
bool eofReached;
|
||||
|
||||
static const unsigned int BUFFER_MORE_AMOUNT = 64;
|
||||
void bufferMore();
|
||||
|
||||
public:
|
||||
BufferedReader(Reader* in);
|
||||
virtual ~BufferedReader();
|
||||
|
||||
virtual void close();
|
||||
virtual int read();
|
||||
virtual int read(wchar_t cbuf[], unsigned int off, unsigned int len);
|
||||
std::wstring readLine();
|
||||
};
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "InputOutputStream.h"
|
||||
|
||||
// Creates ByteArrayInputStream that uses buf as its buffer array. The initial
|
||||
// value of pos is offset and the initial value of count is the minimum of
|
||||
// offset+length and buf.length. The buffer array is not copied. The buffer's
|
||||
// mark is set to the specified offset. Parameters: buf - the input buffer.
|
||||
// offset - the offset in the buffer of the first byte to read.
|
||||
// length - the maximum number of bytes to read from the buffer.
|
||||
ByteArrayInputStream::ByteArrayInputStream(byteArray buf, unsigned int offset,
|
||||
unsigned int length)
|
||||
: pos(offset), count(std::min(offset + length, buf.length)), mark(offset) {
|
||||
this->buf = buf;
|
||||
}
|
||||
|
||||
// Creates a ByteArrayInputStream so that it uses buf as its buffer array. The
|
||||
// buffer array is not copied. The initial value of pos is 0 and the initial
|
||||
// value of count is the length of buf. Parameters: buf - the input buffer.
|
||||
ByteArrayInputStream::ByteArrayInputStream(byteArray buf)
|
||||
: pos(0), count(buf.length), mark(0) {
|
||||
this->buf = buf;
|
||||
}
|
||||
|
||||
// Reads the next byte of data from this input stream. The value byte is
|
||||
// returned as an int in the range 0 to 255. If no byte is available because the
|
||||
// end of the stream has been reached, the value -1 is returned. This read
|
||||
// method cannot block. Returns: the next byte of data, or -1 if the end of the
|
||||
// stream has been reached.
|
||||
int ByteArrayInputStream::read() {
|
||||
if (pos >= count)
|
||||
return -1;
|
||||
else
|
||||
return static_cast<unsigned int>(buf[pos++]);
|
||||
}
|
||||
|
||||
// Reads some number of bytes from the input stream and stores them into the
|
||||
// buffer array b. The number of bytes actually read is returned as an integer.
|
||||
// This method blocks until input data is available, end of file is detected, or
|
||||
// an exception is thrown. If the length of b is zero, then no bytes are read
|
||||
// and 0 is returned; otherwise, there is an attempt to read at least one byte.
|
||||
// If no byte is available because the stream is at the end of the file, the
|
||||
// value -1 is returned; otherwise, at least one byte is read and stored into b.
|
||||
//
|
||||
// The first byte read is stored into element b[0], the next one into b[1], and
|
||||
// so on. The number of bytes read is, at most, equal to the length of b. Let k
|
||||
// be the number of bytes actually read; these bytes will be stored in elements
|
||||
// b[0] through b[k-1], leaving elements b[k] through b[b.length-1] unaffected.
|
||||
//
|
||||
// The read(b) method for class InputStream has the same effect as:
|
||||
//
|
||||
// read(b, 0, b.length)
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 is there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int ByteArrayInputStream::read(byteArray b) { return read(b, 0, b.length); }
|
||||
|
||||
// Reads up to len bytes of data into an array of bytes from this input stream.
|
||||
// If pos equals count, then -1 is returned to indicate end of file. Otherwise,
|
||||
// the number k of bytes read is equal to the smaller of len and count-pos. If k
|
||||
// is positive, then bytes buf[pos] through buf[pos+k-1] are copied into b[off]
|
||||
// through b[off+k-1] in the manner performed by System.arraycopy. The value k
|
||||
// is added into pos and k is returned. This read method cannot block.
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// off - the start offset in the destination array b
|
||||
// len - the maximum number of bytes read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 if there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int ByteArrayInputStream::read(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
if (pos == count) return -1;
|
||||
|
||||
int k = std::min(length, count - pos);
|
||||
XMemCpy(&b[offset], &buf[pos], k);
|
||||
// std::copy( buf->data+pos, buf->data+pos+k, b->data + offset ); // Or this
|
||||
// instead?
|
||||
|
||||
pos += k;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
// Closing a ByteArrayInputStream has no effect.
|
||||
// The methods in this class can be called after the stream has been closed
|
||||
// without generating an IOException.
|
||||
void ByteArrayInputStream::close() { return; }
|
||||
|
||||
// Skips n bytes of input from this input stream. Fewer bytes might be skipped
|
||||
// if the end of the input stream is reached. The actual number k of bytes to be
|
||||
// skipped is equal to the smaller of n and count-pos. The value k is added into
|
||||
// pos and k is returned. Overrides: skip in class InputStream Parameters: n -
|
||||
// the number of bytes to be skipped. Returns: the actual number of bytes
|
||||
// skipped.
|
||||
int64_t ByteArrayInputStream::skip(int64_t n) {
|
||||
int newPos = pos + n;
|
||||
|
||||
if (newPos > count) newPos = count;
|
||||
|
||||
int k = newPos - pos;
|
||||
pos = newPos;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
ByteArrayInputStream::~ByteArrayInputStream() {
|
||||
if (buf.data != nullptr) delete[] buf.data;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class
|
||||
|
||||
#include "InputStream.h"
|
||||
|
||||
class ByteArrayInputStream : public InputStream {
|
||||
protected:
|
||||
byteArray buf; // An array of bytes that was provided by the creator of the
|
||||
// stream.
|
||||
unsigned int count; // The index one greater than the last valid character
|
||||
// in the input stream buffer.
|
||||
unsigned int mark; // The currently marked position in the stream.
|
||||
unsigned int pos; // The index of the next character to read from the input
|
||||
// stream buffer.
|
||||
|
||||
public:
|
||||
ByteArrayInputStream(byteArray buf, unsigned int offset,
|
||||
unsigned int length);
|
||||
ByteArrayInputStream(byteArray buf);
|
||||
virtual ~ByteArrayInputStream();
|
||||
virtual int read();
|
||||
virtual int read(byteArray b);
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual int64_t skip(int64_t n);
|
||||
|
||||
// 4J Stu Added - Sometimes we don't want to delete the data on destroying
|
||||
// this
|
||||
void reset() {
|
||||
buf = byteArray();
|
||||
count = 0;
|
||||
mark = 0;
|
||||
pos = 0;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "ByteArrayOutputStream.h"
|
||||
|
||||
// Creates a new byte array output stream. The buffer capacity is initially 32
|
||||
// bytes, though its size increases if necessary.
|
||||
ByteArrayOutputStream::ByteArrayOutputStream() {
|
||||
count = 0;
|
||||
buf = byteArray(32);
|
||||
}
|
||||
|
||||
// Creates a new byte array output stream, with a buffer capacity of the
|
||||
// specified size, in bytes. Parameters: size - the initial size.
|
||||
ByteArrayOutputStream::ByteArrayOutputStream(unsigned int size) {
|
||||
count = 0;
|
||||
buf = byteArray(size);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream::~ByteArrayOutputStream() {
|
||||
if (buf.data != nullptr) delete[] buf.data;
|
||||
}
|
||||
|
||||
// Writes the specified byte to this byte array output stream.
|
||||
// Parameters:
|
||||
// b - the byte to be written.
|
||||
void ByteArrayOutputStream::write(unsigned int b) {
|
||||
// If we will fill the buffer we need to make it bigger
|
||||
if (count + 1 >= buf.length) buf.resize(buf.length * 2);
|
||||
|
||||
buf[count] = (uint8_t)b;
|
||||
count++;
|
||||
}
|
||||
|
||||
// Writes b.length bytes from the specified byte array to this output stream.
|
||||
// The general contract for write(b) is that it should have exactly the same
|
||||
// effect as the call write(b, 0, b.length).
|
||||
void ByteArrayOutputStream::write(byteArray b) { write(b, 0, b.length); }
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to this
|
||||
// byte array output stream. Parameters: b - the data. off - the start offset in
|
||||
// the data. len - the number of bytes to write.
|
||||
void ByteArrayOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
assert(b.length >= offset + length);
|
||||
|
||||
// If we will fill the buffer we need to make it bigger
|
||||
if (count + length >= buf.length)
|
||||
buf.resize(std::max(count + length + 1, buf.length * 2));
|
||||
|
||||
XMemCpy(&buf[count], &b[offset], length);
|
||||
// std::copy( b->data+offset, b->data+offset+length, buf->data + count ); //
|
||||
// Or this instead?
|
||||
|
||||
count += length;
|
||||
}
|
||||
|
||||
// Closing a ByteArrayOutputStream has no effect.
|
||||
// The methods in this class can be called after the stream has been closed
|
||||
// without generating an IOException.
|
||||
void ByteArrayOutputStream::close() {}
|
||||
|
||||
// Creates a newly allocated byte array. Its size is the current size of this
|
||||
// output stream and the valid contents of the buffer have been copied into it.
|
||||
// Returns:
|
||||
// the current contents of this output stream, as a byte array.
|
||||
byteArray ByteArrayOutputStream::toByteArray() {
|
||||
byteArray out(count);
|
||||
memcpy(out.data, buf.data, count);
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "OutputStream.h"
|
||||
|
||||
class ByteArrayOutputStream : public OutputStream {
|
||||
// Note - when actually implementing, byteArray will need to grow as data is
|
||||
// written
|
||||
public:
|
||||
byteArray buf; // The buffer where data is stored.
|
||||
|
||||
protected:
|
||||
unsigned int count; // The number of valid bytes in the buffer.
|
||||
|
||||
public:
|
||||
ByteArrayOutputStream();
|
||||
ByteArrayOutputStream(unsigned int size);
|
||||
virtual ~ByteArrayOutputStream();
|
||||
|
||||
virtual void flush() {}
|
||||
virtual void write(unsigned int b);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual byteArray toByteArray();
|
||||
|
||||
void reset() { count = 0; }
|
||||
unsigned int size() { return count; }
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
class DataInput {
|
||||
public:
|
||||
virtual int read() = 0;
|
||||
virtual int read(byteArray b) = 0;
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length) = 0;
|
||||
virtual bool readBoolean() = 0;
|
||||
virtual uint8_t readByte() = 0;
|
||||
virtual unsigned char readUnsignedByte() = 0;
|
||||
virtual bool readFully(byteArray a) = 0;
|
||||
virtual double readDouble() = 0;
|
||||
virtual float readFloat() = 0;
|
||||
virtual int readInt() = 0;
|
||||
virtual int64_t readLong() = 0;
|
||||
virtual short readShort() = 0;
|
||||
virtual wchar_t readChar() = 0;
|
||||
virtual std::wstring readUTF() = 0;
|
||||
virtual PlayerUID readPlayerUID() = 0; // 4J Added
|
||||
virtual int skipBytes(int n) = 0;
|
||||
};
|
||||
@@ -0,0 +1,611 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "DataInputStream.h"
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
|
||||
// Creates a DataInputStream that uses the specified underlying InputStream.
|
||||
// Parameters:
|
||||
// in - the specified input stream
|
||||
DataInputStream::DataInputStream(InputStream* in) : stream(in) {}
|
||||
|
||||
// Reads the next byte of data from this input stream. The value byte is
|
||||
// returned as an int in the range 0 to 255. If no byte is available because the
|
||||
// end of the stream has been reached, the value -1 is returned. This method
|
||||
// blocks until input data is available, the end of the stream is detected, or
|
||||
// an exception is thrown. This method simply performs in.read() and returns the
|
||||
// result.
|
||||
int DataInputStream::read() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::read() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return -1;
|
||||
}
|
||||
return stream->read();
|
||||
}
|
||||
|
||||
// Reads some number of bytes from the contained input stream and stores them
|
||||
// into the buffer array b. The number of bytes actually read is returned as an
|
||||
// integer. This method blocks until input data is available, end of file is
|
||||
// detected, or an exception is thrown. If b is null, a NullPointerException is
|
||||
// thrown. If the length of b is zero, then no bytes are read and 0 is returned;
|
||||
// otherwise, there is an attempt to read at least one byte. If no byte is
|
||||
// available because the stream is at end of file, the value -1 is returned;
|
||||
// otherwise, at least one byte is read and stored into b.
|
||||
//
|
||||
// The first byte read is stored into element b[0], the next one into b[1], and
|
||||
// so on. The number of bytes read is, at most, equal to the length of b. Let k
|
||||
// be the number of bytes actually read; these bytes will be stored in elements
|
||||
// b[0] through b[k-1], leaving elements b[k] through b[b.length-1] unaffected.
|
||||
//
|
||||
// The read(b) method has the same effect as:
|
||||
//
|
||||
// read(b, 0, b.length)
|
||||
//
|
||||
// Overrides:
|
||||
// read in class FilterInputStream
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 if there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int DataInputStream::read(byteArray b) {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::read(byteArray) called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return -1;
|
||||
}
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
// Reads up to len bytes of data from the contained input stream into an array
|
||||
// of bytes. An attempt is made to read as many as len bytes, but a smaller
|
||||
// number may be read, possibly zero. The number of bytes actually read is
|
||||
// returned as an integer. This method blocks until input data is available, end
|
||||
// of file is detected, or an exception is thrown.
|
||||
//
|
||||
// If len is zero, then no bytes are read and 0 is returned; otherwise, there is
|
||||
// an attempt to read at least one byte. If no byte is available because the
|
||||
// stream is at end of file, the value -1 is returned; otherwise, at least one
|
||||
// byte is read and stored into b.
|
||||
//
|
||||
// The first byte read is stored into element b[off], the next one into
|
||||
// b[off+1], and so on. The number of bytes read is, at most, equal to len. Let
|
||||
// k be the number of bytes actually read; these bytes will be stored in
|
||||
// elements b[off] through b[off+k-1], leaving elements b[off+k] through
|
||||
// b[off+len-1] unaffected.
|
||||
//
|
||||
// In every case, elements b[0] through b[off] and elements b[off+len] through
|
||||
// b[b.length-1] are unaffected.
|
||||
//
|
||||
// Overrides:
|
||||
// read in class FilterInputStream
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
// off - the start offset in the destination array b
|
||||
// len - the maximum number of bytes read.
|
||||
// Returns:
|
||||
// the total number of bytes read into the buffer, or -1 if there is no more
|
||||
// data because the end of the stream has been reached.
|
||||
int DataInputStream::read(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::read(byteArray,offset,length) called but "
|
||||
"underlying stream is nullptr\n");
|
||||
return -1;
|
||||
}
|
||||
return stream->read(b, offset, length);
|
||||
}
|
||||
|
||||
// Closes this input stream and releases any system resources associated with
|
||||
// the stream. This method simply performs in.close()
|
||||
void DataInputStream::close() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::close() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->close();
|
||||
}
|
||||
|
||||
// Reads one input byte and returns true if that byte is nonzero, false if that
|
||||
// byte is zero. This method is suitable for reading the byte written by the
|
||||
// writeBoolean method of interface DataOutput. Returns: the bool value read.
|
||||
bool DataInputStream::readBoolean() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readBoolean() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return false;
|
||||
}
|
||||
return stream->read() != 0;
|
||||
}
|
||||
|
||||
// Reads and returns one input byte. The byte is treated as a signed value in
|
||||
// the range -128 through 127, inclusive. This method is suitable for reading
|
||||
// the byte written by the writeByte method of interface DataOutput. Returns:
|
||||
// the 8-bit value read.
|
||||
uint8_t DataInputStream::readByte() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readByte() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
return (uint8_t)stream->read();
|
||||
}
|
||||
|
||||
unsigned char DataInputStream::readUnsignedByte() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readUnsignedByte() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
return (unsigned char)stream->read();
|
||||
}
|
||||
|
||||
// Reads two input bytes and returns a char value. Let a be the first byte read
|
||||
// and b be the second byte. The value returned is: (char)((a << 8) | (b &
|
||||
// 0xff))
|
||||
//
|
||||
// This method is suitable for reading bytes written by the writeChar method of
|
||||
// interface DataOutput. Returns: the char value read.
|
||||
wchar_t DataInputStream::readChar() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readChar() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
return (wchar_t)((a << 8) | (b & 0xff));
|
||||
}
|
||||
|
||||
// Reads some bytes from an input stream and stores them into the buffer array
|
||||
// b. The number of bytes read is equal to the length of b. This method blocks
|
||||
// until one of the following conditions occurs:
|
||||
//
|
||||
// b.length bytes of input data are available, in which case a normal return is
|
||||
// made. End of file is detected, in which case an EOFException is thrown. An
|
||||
// I/O error occurs, in which case an IOException other than EOFException is
|
||||
// thrown. If b is null, a NullPointerException is thrown. If b.length is zero,
|
||||
// then no bytes are read. Otherwise, the first byte read is stored into element
|
||||
// b[0], the next one into b[1], and so on. If an exception is thrown from this
|
||||
// method, then it may be that some but not all bytes of b have been updated
|
||||
// with data from the input stream.
|
||||
//
|
||||
// Parameters:
|
||||
// b - the buffer into which the data is read.
|
||||
bool DataInputStream::readFully(byteArray b) {
|
||||
// TODO 4J Stu - I am not entirely sure if this matches the implementation
|
||||
// of the Java library
|
||||
// TODO 4J Stu - Need to handle exceptions here is we throw them in other
|
||||
// InputStreams
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readFully(byteArray) but underlying stream is "
|
||||
"nullptr\n");
|
||||
return false;
|
||||
}
|
||||
for (unsigned int i = 0; i < b.length; i++) {
|
||||
int byteRead = stream->read();
|
||||
if (byteRead == -1) {
|
||||
return false;
|
||||
} else {
|
||||
b[i] = static_cast<uint8_t>(byteRead);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataInputStream::readFully(charArray b) {
|
||||
// TODO 4J Stu - I am not entirely sure if this matches the implementation
|
||||
// of the Java library
|
||||
// TODO 4J Stu - Need to handle exceptions here is we throw them in other
|
||||
// InputStreams
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readFully(charArray) but underlying stream is "
|
||||
"nullptr\n");
|
||||
return false;
|
||||
}
|
||||
for (unsigned int i = 0; i < b.length; i++) {
|
||||
int byteRead = stream->read();
|
||||
if (byteRead == -1) {
|
||||
return false;
|
||||
} else {
|
||||
b[i] = byteRead;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reads eight input bytes and returns a double value. It does this by first
|
||||
// constructing a long value in exactly the manner of the readlong method, then
|
||||
// converting this long value to a double in exactly the manner of the method
|
||||
// Double.longBitsToDouble. This method is suitable for reading bytes written by
|
||||
// the writeDouble method of interface DataOutput. Returns: the double value
|
||||
// read.
|
||||
double DataInputStream::readDouble() {
|
||||
int64_t bits = readLong();
|
||||
|
||||
return std::bit_cast<double>(bits);
|
||||
}
|
||||
|
||||
// Reads four input bytes and returns a float value. It does this by first
|
||||
// constructing an int value in exactly the manner of the readInt method, then
|
||||
// converting this int value to a float in exactly the manner of the method
|
||||
// Float.intBitsToFloat. This method is suitable for reading bytes written by
|
||||
// the writeFloat method of interface DataOutput. Returns: the float value read.
|
||||
float DataInputStream::readFloat() {
|
||||
int bits = readInt();
|
||||
|
||||
return std::bit_cast<float>(bits);
|
||||
}
|
||||
|
||||
// Reads four input bytes and returns an int value. Let a-d be the first through
|
||||
// fourth bytes read. The value returned is:
|
||||
//
|
||||
// (((a & 0xff) << 24) | ((b & 0xff) << 16) |
|
||||
// ((c & 0xff) << 8) | (d & 0xff))
|
||||
//
|
||||
// This method is suitable for reading bytes written by the writeInt method of
|
||||
// interface DataOutput. Returns: the int value read.
|
||||
int DataInputStream::readInt() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readInt() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
int c = stream->read();
|
||||
int d = stream->read();
|
||||
int bits = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) |
|
||||
(d & 0xff));
|
||||
return bits;
|
||||
}
|
||||
|
||||
// Reads eight input bytes and returns a long value. Let a-h be the first
|
||||
// through eighth bytes read. The value returned is:
|
||||
//
|
||||
// (((long)(a & 0xff) << 56) |
|
||||
// ((long)(b & 0xff) << 48) |
|
||||
// ((long)(c & 0xff) << 40) |
|
||||
// ((long)(d & 0xff) << 32) |
|
||||
// ((long)(e & 0xff) << 24) |
|
||||
// ((long)(f & 0xff) << 16) |
|
||||
// ((long)(g & 0xff) << 8) |
|
||||
// ((long)(h & 0xff)))
|
||||
//
|
||||
// This method is suitable for reading bytes written by the writeLong method of
|
||||
// interface DataOutput.
|
||||
//
|
||||
// Returns:
|
||||
// the long value read.
|
||||
int64_t DataInputStream::readLong() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readLong() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int64_t a = stream->read();
|
||||
int64_t b = stream->read();
|
||||
int64_t c = stream->read();
|
||||
int64_t d = stream->read();
|
||||
int64_t e = stream->read();
|
||||
int64_t f = stream->read();
|
||||
int64_t g = stream->read();
|
||||
int64_t h = stream->read();
|
||||
|
||||
int64_t bits =
|
||||
(((a & 0xff) << 56) | ((b & 0xff) << 48) | ((c & 0xff) << 40) |
|
||||
((d & 0xff) << 32) | ((e & 0xff) << 24) | ((f & 0xff) << 16) |
|
||||
((g & 0xff) << 8) | ((h & 0xff)));
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
// Reads two input bytes and returns a short value. Let a be the first byte read
|
||||
// and b be the second byte. The value returned is: (short)((a << 8) | (b &
|
||||
// 0xff))
|
||||
//
|
||||
// This method is suitable for reading the bytes written by the writeShort
|
||||
// method of interface DataOutput. Returns: the 16-bit value read.
|
||||
short DataInputStream::readShort() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readShort() but underlying stream is nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
return (short)((a << 8) | (b & 0xff));
|
||||
}
|
||||
|
||||
unsigned short DataInputStream::readUnsignedShort() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readUnsignedShort() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return 0;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
return static_cast<unsigned short>(((a & 0xff) << 8) | (b & 0xff));
|
||||
}
|
||||
|
||||
// Reads in a string that has been encoded using a modified UTF-8 format. The
|
||||
// general contract of readUTF is that it reads a representation of a Unicode
|
||||
// character string encoded in modified UTF-8 format; this string of characters
|
||||
// is then returned as a String. First, two bytes are read and used to construct
|
||||
// an unsigned 16-bit integer in exactly the manner of the readUnsignedShort
|
||||
// method . This integer value is called the UTF length and specifies the number
|
||||
// of additional bytes to be read. These bytes are then converted to characters
|
||||
// by considering them in groups. The length of each group is computed from the
|
||||
// value of the first byte of the group. The byte following a group, if any, is
|
||||
// the first byte of the next group.
|
||||
//
|
||||
// If the first byte of a group matches the bit pattern 0xxxxxxx (where x means
|
||||
// "may be 0 or 1"), then the group consists of just that byte. The byte is
|
||||
// zero-extended to form a character.
|
||||
//
|
||||
// If the first byte of a group matches the bit pattern 110xxxxx, then the group
|
||||
// consists of that byte a and a second byte b. If there is no byte b (because
|
||||
// byte a was the last of the bytes to be read), or if byte b does not match the
|
||||
// bit pattern 10xxxxxx, then a UTFDataFormatException is thrown. Otherwise, the
|
||||
// group is converted to the character:
|
||||
//
|
||||
//(char)(((a& 0x1F) << 6) | (b & 0x3F))
|
||||
//
|
||||
// If the first byte of a group matches the bit pattern 1110xxxx, then the group
|
||||
// consists of that byte a and two more bytes b and c. If there is no byte c
|
||||
// (because byte a was one of the last two of the bytes to be read), or either
|
||||
// byte b or byte c does not match the bit pattern 10xxxxxx, then a
|
||||
// UTFDataFormatException is thrown. Otherwise, the group is converted to the
|
||||
// character:
|
||||
//
|
||||
// (char)(((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F))
|
||||
//
|
||||
// If the first byte of a group matches the pattern 1111xxxx or the pattern
|
||||
// 10xxxxxx, then a UTFDataFormatException is thrown. If end of file is
|
||||
// encountered at any time during this entire process, then an EOFException is
|
||||
// thrown.
|
||||
//
|
||||
// After every group has been converted to a character by this process, the
|
||||
// characters are gathered, in the same order in which their corresponding
|
||||
// groups were read from the input stream, to form a String, which is returned.
|
||||
//
|
||||
// The writeUTF method of interface DataOutput may be used to write data that is
|
||||
// suitable for reading by this method.
|
||||
//
|
||||
// Returns:
|
||||
// a Unicode string.
|
||||
std::wstring DataInputStream::readUTF() {
|
||||
std::wstring outputString;
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readUTF() but underlying stream is nullptr\n");
|
||||
return outputString;
|
||||
}
|
||||
int a = stream->read();
|
||||
int b = stream->read();
|
||||
unsigned short UTFLength = (unsigned short)(((a & 0xff) << 8) | (b & 0xff));
|
||||
|
||||
//// 4J Stu - I decided while writing DataOutputStream that we didn't need
|
||||
/// to bother using the UTF8 format / used in the java libs, and just write
|
||||
/// in/out as wchar_t all the time
|
||||
|
||||
/*for( unsigned short i = 0; i < UTFLength; i++)
|
||||
{
|
||||
wchar_t theChar = readChar();
|
||||
outputString.push_back(theChar);
|
||||
}*/
|
||||
|
||||
unsigned short currentByteIndex = 0;
|
||||
while (currentByteIndex < UTFLength) {
|
||||
int firstByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
if (firstByte == -1)
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
|
||||
// Masking patterns:
|
||||
// 10000000 = 0x80 // Match only highest bit
|
||||
// 11000000 = 0xC0 // Match only highest two bits
|
||||
// 11100000 = 0xE0 // Match only highest three bits
|
||||
// 11110000 = 0xF0 // Match only highest four bits
|
||||
|
||||
// Matching patterns:
|
||||
// 10xxxxxx = 0x80 // ERROR, or second/third byte
|
||||
// 1111xxxx = 0xF0 //ERROR
|
||||
// 0xxxxxxx = 0x00 // One byte UTF
|
||||
// 110xxxxx = 0xC0 // Two byte UTF
|
||||
// 1110xxxx = 0xE0 // Three byte UTF
|
||||
if (((firstByte & 0xC0) == 0x80) || ((firstByte & 0xF0) == 0xF0)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
} else if ((firstByte & 0x80) == 0x00) {
|
||||
// One byte UTF
|
||||
wchar_t readChar = (wchar_t)firstByte;
|
||||
outputString.push_back(readChar);
|
||||
continue;
|
||||
} else if ((firstByte & 0xE0) == 0xC0) {
|
||||
// Two byte UTF
|
||||
|
||||
// No more bytes to read
|
||||
if (!(currentByteIndex < UTFLength)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
int secondByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
}
|
||||
// Incorrect second byte pattern
|
||||
else if ((secondByte & 0xC0) != 0x80) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
wchar_t readChar =
|
||||
(wchar_t)(((firstByte & 0x1F) << 6) | (secondByte & 0x3F));
|
||||
outputString.push_back(readChar);
|
||||
continue;
|
||||
} else if ((firstByte & 0xF0) == 0xE0) {
|
||||
// Three byte UTF
|
||||
|
||||
// No more bytes to read
|
||||
if (!(currentByteIndex < UTFLength)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
int secondByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
}
|
||||
|
||||
// No more bytes to read
|
||||
if (!(currentByteIndex < UTFLength)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
int thirdByte = stream->read();
|
||||
currentByteIndex++;
|
||||
|
||||
// No third byte
|
||||
if (thirdByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
break;
|
||||
}
|
||||
// Incorrect second or third byte pattern
|
||||
else if (((secondByte & 0xC0) != 0x80) ||
|
||||
((thirdByte & 0xC0) != 0x80)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
break;
|
||||
}
|
||||
|
||||
wchar_t readChar =
|
||||
(wchar_t)(((firstByte & 0x0F) << 12) |
|
||||
((secondByte & 0x3F) << 6) | (thirdByte & 0x3F));
|
||||
outputString.push_back(readChar);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return outputString;
|
||||
}
|
||||
|
||||
int DataInputStream::readUTFChar() {
|
||||
int returnValue = -1;
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataInputStream::readUTFChar() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return returnValue;
|
||||
}
|
||||
int firstByte = stream->read();
|
||||
|
||||
if (firstByte == -1)
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
|
||||
// Masking patterns:
|
||||
// 10000000 = 0x80 // Match only highest bit
|
||||
// 11000000 = 0xC0 // Match only highest two bits
|
||||
// 11100000 = 0xE0 // Match only highest three bits
|
||||
// 11110000 = 0xF0 // Match only highest four bits
|
||||
|
||||
// Matching patterns:
|
||||
// 10xxxxxx = 0x80 // ERROR, or second/third byte
|
||||
// 1111xxxx = 0xF0 //ERROR
|
||||
// 0xxxxxxx = 0x00 // One byte UTF
|
||||
// 110xxxxx = 0xC0 // Two byte UTF
|
||||
// 1110xxxx = 0xE0 // Three byte UTF
|
||||
if (((firstByte & 0xC0) == 0x80) || ((firstByte & 0xF0) == 0xF0)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
return returnValue;
|
||||
} else if ((firstByte & 0x80) == 0x00) {
|
||||
// One byte UTF
|
||||
returnValue = firstByte;
|
||||
} else if ((firstByte & 0xE0) == 0xC0) {
|
||||
// Two byte UTF
|
||||
int secondByte = stream->read();
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
}
|
||||
// Incorrect second byte pattern
|
||||
else if ((secondByte & 0xC0) != 0x80) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
returnValue = ((firstByte & 0x1F) << 6) | (secondByte & 0x3F);
|
||||
} else if ((firstByte & 0xF0) == 0xE0) {
|
||||
// Three byte UTF
|
||||
|
||||
int secondByte = stream->read();
|
||||
|
||||
// No second byte
|
||||
if (secondByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
int thirdByte = stream->read();
|
||||
|
||||
// No third byte
|
||||
if (thirdByte == -1) {
|
||||
// TODO 4J Stu - EOFException
|
||||
return returnValue;
|
||||
}
|
||||
// Incorrect second or third byte pattern
|
||||
else if (((secondByte & 0xC0) != 0x80) ||
|
||||
((thirdByte & 0xC0) != 0x80)) {
|
||||
// TODO 4J Stu - UTFDataFormatException
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
returnValue = (((firstByte & 0x0F) << 12) | ((secondByte & 0x3F) << 6) |
|
||||
(thirdByte & 0x3F));
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
PlayerUID DataInputStream::readPlayerUID() {
|
||||
PlayerUID returnValue;
|
||||
returnValue = readLong();
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void DataInputStream::deleteChildStream() { delete stream; }
|
||||
|
||||
// Skips n bytes of input from this input stream. Fewer bytes might be skipped
|
||||
// if the end of the input stream is reached. The actual number k of bytes to be
|
||||
// skipped is equal to the smaller of n and count-pos. The value k is added into
|
||||
// pos and k is returned. Overrides: skip in class InputStream Parameters: n -
|
||||
// the number of bytes to be skipped. Returns: the actual number of bytes
|
||||
// skipped.
|
||||
int64_t DataInputStream::skip(int64_t n) { return stream->skip(n); }
|
||||
|
||||
int DataInputStream::skipBytes(int n) { return skip(n); }
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class (although we miss out an
|
||||
// intermediate inheritance class that we don't care about)
|
||||
|
||||
#include "InputStream.h"
|
||||
#include "DataInput.h"
|
||||
|
||||
class DataInputStream : public InputStream, public DataInput {
|
||||
private:
|
||||
InputStream* stream;
|
||||
|
||||
public:
|
||||
DataInputStream(InputStream* in);
|
||||
virtual int read();
|
||||
virtual int read(byteArray b);
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual bool readBoolean();
|
||||
virtual uint8_t readByte();
|
||||
virtual unsigned char readUnsignedByte();
|
||||
virtual wchar_t readChar();
|
||||
virtual bool readFully(byteArray b);
|
||||
virtual bool readFully(charArray b);
|
||||
virtual double readDouble();
|
||||
virtual float readFloat();
|
||||
virtual int readInt();
|
||||
virtual int64_t readLong();
|
||||
virtual short readShort();
|
||||
virtual unsigned short readUnsignedShort();
|
||||
virtual std::wstring readUTF();
|
||||
void deleteChildStream();
|
||||
virtual int readUTFChar();
|
||||
virtual PlayerUID readPlayerUID(); // 4J Added
|
||||
virtual int64_t skip(int64_t n);
|
||||
virtual int skipBytes(int n);
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
class DataOutput {
|
||||
public:
|
||||
virtual void write(unsigned int b) = 0;
|
||||
virtual void write(byteArray b) = 0;
|
||||
virtual void write(byteArray b, unsigned int offset,
|
||||
unsigned int length) = 0;
|
||||
virtual void writeByte(uint8_t a) = 0;
|
||||
virtual void writeDouble(double a) = 0;
|
||||
virtual void writeFloat(float a) = 0;
|
||||
virtual void writeInt(int a) = 0;
|
||||
virtual void writeLong(int64_t a) = 0;
|
||||
virtual void writeShort(short a) = 0;
|
||||
virtual void writeBoolean(bool v) = 0;
|
||||
virtual void writeChar(wchar_t v) = 0;
|
||||
virtual void writeChars(const std::wstring& s) = 0;
|
||||
virtual void writeUTF(const std::wstring& a) = 0;
|
||||
virtual void writePlayerUID(PlayerUID player) = 0; // 4J Added
|
||||
};
|
||||
@@ -0,0 +1,259 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "DataOutputStream.h"
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
|
||||
// Creates a new data output stream to write data to the specified underlying
|
||||
// output stream. The counter written is set to zero. Parameters: out - the
|
||||
// underlying output stream, to be saved for later use.
|
||||
DataOutputStream::DataOutputStream(OutputStream* out)
|
||||
: stream(out), written(0) {}
|
||||
|
||||
// 4J Stu - We cannot always delete the stream when we are destroyed, but we
|
||||
// want to clear it up as there are occasions when we don't have a handle to the
|
||||
// child stream elsewhere and want to delete it
|
||||
void DataOutputStream::deleteChildStream() { delete stream; }
|
||||
|
||||
// Writes the specified byte (the low eight bits of the argument b) to the
|
||||
// underlying output stream. If no exception is thrown, the counter written is
|
||||
// incremented by 1. Implements the write method of OutputStream. Parameters: b
|
||||
// - the byte to be written.
|
||||
void DataOutputStream::write(unsigned int b) {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataOutputStream::write(unsigned int) called but underlying "
|
||||
"stream is nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->write(b);
|
||||
// TODO 4J Stu - Exception handling?
|
||||
written++;
|
||||
}
|
||||
|
||||
void DataOutputStream::flush() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataOutputStream::flush() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->flush();
|
||||
}
|
||||
|
||||
// Writes b.length bytes from the specified byte array to this output stream.
|
||||
// The general contract for write(b) is that it should have exactly the same
|
||||
// effect as the call write(b, 0, b.length). Parameters: b - the data.
|
||||
void DataOutputStream::write(byteArray b) { write(b, 0, b.length); }
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to the
|
||||
// underlying output stream. If no exception is thrown, the counter written is
|
||||
// incremented by len. Parameters: b - the data. off - the start offset in the
|
||||
// data. len - the number of bytes to write.
|
||||
void DataOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataOutputStream::write(byteArray,...) called but underlying "
|
||||
"stream is nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->write(b, offset, length);
|
||||
// TODO 4J Stu - Some form of error checking?
|
||||
written += length;
|
||||
}
|
||||
|
||||
// Closes this output stream and releases any system resources associated with
|
||||
// the stream. The close method of FilterOutputStream calls its flush method,
|
||||
// and then calls the close method of its underlying output stream.
|
||||
void DataOutputStream::close() {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataOutputStream::close() called but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->close();
|
||||
}
|
||||
|
||||
// Writes out a byte to the underlying output stream as a 1-byte value. If no
|
||||
// exception is thrown, the counter written is incremented by 1. Parameters: v -
|
||||
// a byte value to be written.
|
||||
void DataOutputStream::writeByte(uint8_t a) {
|
||||
stream->write(static_cast<unsigned int>(a));
|
||||
}
|
||||
|
||||
// Converts the double argument to a long using the doubleToLongBits method in
|
||||
// class Double, and then writes that long value to the underlying output stream
|
||||
// as an 8-byte quantity, high byte first. If no exception is thrown, the
|
||||
// counter written is incremented by 8. Parameters: v - a double value to be
|
||||
// written.
|
||||
void DataOutputStream::writeDouble(double a) {
|
||||
int64_t bits = std::bit_cast<int64_t>(a);
|
||||
|
||||
writeLong(bits);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 8;
|
||||
}
|
||||
|
||||
// Converts the float argument to an int using the floatToIntBits method in
|
||||
// class Float, and then writes that int value to the underlying output stream
|
||||
// as a 4-byte quantity, high byte first. If no exception is thrown, the counter
|
||||
// written is incremented by 4. Parameters: v - a float value to be written.
|
||||
void DataOutputStream::writeFloat(float a) {
|
||||
int bits = std::bit_cast<int>(a);
|
||||
|
||||
writeInt(bits);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 4;
|
||||
}
|
||||
|
||||
// Writes an int to the underlying output stream as four bytes, high byte first.
|
||||
// If no exception is thrown, the counter written is incremented by 4.
|
||||
// Parameters:
|
||||
// v - an int to be written.
|
||||
void DataOutputStream::writeInt(int a) {
|
||||
stream->write((a >> 24) & 0xff);
|
||||
stream->write((a >> 16) & 0xff);
|
||||
stream->write((a >> 8) & 0xff);
|
||||
stream->write(a & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 4;
|
||||
}
|
||||
|
||||
// Writes a long to the underlying output stream as eight bytes, high byte
|
||||
// first. In no exception is thrown, the counter written is incremented by 8.
|
||||
// Parameters:
|
||||
// v - a long to be written.
|
||||
void DataOutputStream::writeLong(int64_t a) {
|
||||
stream->write((a >> 56) & 0xff);
|
||||
stream->write((a >> 48) & 0xff);
|
||||
stream->write((a >> 40) & 0xff);
|
||||
stream->write((a >> 32) & 0xff);
|
||||
stream->write((a >> 24) & 0xff);
|
||||
stream->write((a >> 16) & 0xff);
|
||||
stream->write((a >> 8) & 0xff);
|
||||
stream->write(a & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 4;
|
||||
}
|
||||
|
||||
// Writes a short to the underlying output stream as two bytes, high byte first.
|
||||
// If no exception is thrown, the counter written is incremented by 2.
|
||||
// Parameters:
|
||||
// v - a short to be written.
|
||||
void DataOutputStream::writeShort(short a) {
|
||||
stream->write((a >> 8) & 0xff);
|
||||
stream->write(a & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 2;
|
||||
}
|
||||
|
||||
void DataOutputStream::writeUnsignedShort(unsigned short a) {
|
||||
if (stream == nullptr) {
|
||||
app.DebugPrintf(
|
||||
"DataOutputStream::writeUnsignedShort() but underlying stream is "
|
||||
"nullptr\n");
|
||||
return;
|
||||
}
|
||||
stream->write(static_cast<unsigned int>((a >> 8) & 0xff));
|
||||
stream->write(static_cast<unsigned int>(a & 0xff));
|
||||
written += 2;
|
||||
}
|
||||
|
||||
// Writes a char to the underlying output stream as a 2-byte value, high byte
|
||||
// first. If no exception is thrown, the counter written is incremented by 2.
|
||||
// Parameters:
|
||||
// v - a char value to be written.
|
||||
void DataOutputStream::writeChar(wchar_t v) {
|
||||
stream->write((v >> 8) & 0xff);
|
||||
stream->write(v & 0xff);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 2;
|
||||
}
|
||||
|
||||
// Writes a string to the underlying output stream as a sequence of characters.
|
||||
// Each character is written to the data output stream as if by the writeChar
|
||||
// method. If no exception is thrown, the counter written is incremented by
|
||||
// twice the length of s. Parameters: s - a String value to be written.
|
||||
void DataOutputStream::writeChars(const std::wstring& str) {
|
||||
for (unsigned int i = 0; i < str.length(); i++) {
|
||||
writeChar(str.at(i));
|
||||
// TODO 4J Stu - Error handling?
|
||||
}
|
||||
// Incrementing handled by the writeChar function
|
||||
}
|
||||
|
||||
// Writes a bool to the underlying output stream as a 1-byte value.
|
||||
// The value true is written out as the value (uint8_t)1; the value false is
|
||||
// written out as the value (uint8_t)0. If no exception is thrown, the counter
|
||||
// written is incremented by 1. Parameters: v - a bool value to be written.
|
||||
void DataOutputStream::writeBoolean(bool b) {
|
||||
stream->write(b ? 1 : 0);
|
||||
// TODO 4J Stu - Error handling?
|
||||
written += 1;
|
||||
}
|
||||
|
||||
// Writes a string to the underlying output stream using modified UTF-8 encoding
|
||||
// in a machine-independent manner. First, two bytes are written to the output
|
||||
// stream as if by the writeShort method giving the number of bytes to follow.
|
||||
// This value is the number of bytes actually written out, not the length of the
|
||||
// string. Following the length, each character of the string is output, in
|
||||
// sequence, using the modified UTF-8 encoding for the character. If no
|
||||
// exception is thrown, the counter written is incremented by the total number
|
||||
// of bytes written to the output stream. This will be at least two plus the
|
||||
// length of str, and at most two plus thrice the length of str. Parameters: str
|
||||
// - a string to be written.
|
||||
void DataOutputStream::writeUTF(const std::wstring& str) {
|
||||
int strlen = (int)str.length();
|
||||
int utflen = 0;
|
||||
int c, count = 0;
|
||||
|
||||
/* use charAt instead of copying String to char array */
|
||||
for (int i = 0; i < strlen; i++) {
|
||||
c = str.at(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
utflen++;
|
||||
} else if (c > 0x07FF) {
|
||||
utflen += 3;
|
||||
} else {
|
||||
utflen += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// if (utflen > 65535)
|
||||
// throw new UTFDataFormatException(
|
||||
// "encoded string too long: " + utflen + " bytes");
|
||||
|
||||
byteArray bytearr(utflen + 2);
|
||||
|
||||
bytearr[count++] = (uint8_t)((utflen >> 8) & 0xFF);
|
||||
bytearr[count++] = (uint8_t)((utflen >> 0) & 0xFF);
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < strlen; i++) {
|
||||
c = str.at(i);
|
||||
if (!((c >= 0x0001) && (c <= 0x007F))) break;
|
||||
bytearr[count++] = (uint8_t)c;
|
||||
}
|
||||
|
||||
for (; i < strlen; i++) {
|
||||
c = str.at(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
bytearr[count++] = (uint8_t)c;
|
||||
|
||||
} else if (c > 0x07FF) {
|
||||
bytearr[count++] = (uint8_t)(0xE0 | ((c >> 12) & 0x0F));
|
||||
bytearr[count++] = (uint8_t)(0x80 | ((c >> 6) & 0x3F));
|
||||
bytearr[count++] = (uint8_t)(0x80 | ((c >> 0) & 0x3F));
|
||||
} else {
|
||||
bytearr[count++] = (uint8_t)(0xC0 | ((c >> 6) & 0x1F));
|
||||
bytearr[count++] = (uint8_t)(0x80 | ((c >> 0) & 0x3F));
|
||||
}
|
||||
}
|
||||
write(bytearr, 0, utflen + 2);
|
||||
delete[] bytearr.data;
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
void DataOutputStream::writePlayerUID(PlayerUID player) { writeLong(player); }
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class (although we miss out an
|
||||
// intermediate inheritance class that we don't care about)
|
||||
|
||||
#include "OutputStream.h"
|
||||
#include "DataOutput.h"
|
||||
|
||||
class DataOutputStream : public OutputStream, public DataOutput {
|
||||
private:
|
||||
OutputStream* stream;
|
||||
|
||||
protected:
|
||||
int written; // The number of bytes written to the data output stream so
|
||||
// far.
|
||||
|
||||
public:
|
||||
DataOutputStream(OutputStream* out);
|
||||
|
||||
// 4J Stu Added
|
||||
void deleteChildStream();
|
||||
|
||||
virtual void write(unsigned int b);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual void writeByte(uint8_t a);
|
||||
virtual void writeDouble(double a);
|
||||
virtual void writeFloat(float a);
|
||||
virtual void writeInt(int a);
|
||||
virtual void writeLong(int64_t a);
|
||||
virtual void writeShort(short a);
|
||||
virtual void writeUnsignedShort(unsigned short a);
|
||||
virtual void writeChar(wchar_t a);
|
||||
virtual void writeChars(const std::wstring& a);
|
||||
virtual void writeBoolean(bool b);
|
||||
virtual void writeUTF(const std::wstring& a);
|
||||
virtual void writePlayerUID(PlayerUID player);
|
||||
virtual void flush();
|
||||
};
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "../File.h"
|
||||
#include "FileInputStream.h"
|
||||
#include <algorithm>
|
||||
|
||||
extern CConsoleMinecraftApp app;
|
||||
|
||||
namespace {
|
||||
int64_t FileTell(std::FILE* file) {
|
||||
#if defined(_WIN32)
|
||||
return _ftelli64(file);
|
||||
#else
|
||||
return static_cast<int64_t>(ftello(file));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FileSeek(std::FILE* file, int64_t offset, int origin) {
|
||||
#if defined(_WIN32)
|
||||
return _fseeki64(file, offset, origin) == 0;
|
||||
#else
|
||||
return fseeko(file, static_cast<off_t>(offset), origin) == 0;
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Creates a FileInputStream by opening a connection to an actual file, the file
|
||||
// named by the File object file in the file system. A new FileDescriptor object
|
||||
// is created to represent this file connection. First, if there is a security
|
||||
// manager, its checkRead method is called with the path represented by the file
|
||||
// argument as its argument.
|
||||
//
|
||||
// If the named file does not exist, is a directory rather than a regular file,
|
||||
// or for some other reason cannot be opened for reading then a
|
||||
// FileNotFoundException is thrown.
|
||||
//
|
||||
// Parameters:
|
||||
// file - the file to be opened for reading.
|
||||
// Throws:
|
||||
// FileNotFoundException - if the file does not exist, is a directory rather
|
||||
// than a regular file, or for some other reason cannot be opened for reading.
|
||||
// SecurityException - if a security manager exists and its checkRead method
|
||||
// denies read access to the file.
|
||||
FileInputStream::FileInputStream(const File& file) : m_fileHandle(nullptr) {
|
||||
#if defined(_WIN32)
|
||||
m_fileHandle = _wfopen(file.getPath().c_str(), L"rb");
|
||||
#else
|
||||
const std::string nativePath = wstringtofilename(file.getPath());
|
||||
m_fileHandle = std::fopen(nativePath.c_str(), "rb");
|
||||
#endif
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
// TODO 4J Stu - Any form of error/exception handling
|
||||
//__debugbreak();
|
||||
app.FatalLoadError();
|
||||
}
|
||||
}
|
||||
|
||||
FileInputStream::~FileInputStream() {
|
||||
if (m_fileHandle != nullptr) {
|
||||
std::fclose(m_fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Reads a byte of data from this input stream. This method blocks if no input
|
||||
// is yet available. Returns: the next byte of data, or -1 if the end of the
|
||||
// file is reached.
|
||||
int FileInputStream::read() {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::uint8_t byteRead = static_cast<std::uint8_t>(0);
|
||||
const size_t numberOfBytesRead = std::fread(&byteRead, 1, 1, m_fileHandle);
|
||||
|
||||
if (std::ferror(m_fileHandle) != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
app.FatalLoadError();
|
||||
// return -1;
|
||||
} else if (numberOfBytesRead == 0) {
|
||||
// File pointer is past the end of the file
|
||||
return -1;
|
||||
}
|
||||
|
||||
return static_cast<int>(byteRead);
|
||||
}
|
||||
|
||||
// Reads up to b.length bytes of data from this input stream into an array of
|
||||
// bytes. This method blocks until some input is available. Parameters: b - the
|
||||
// buffer into which the data is read. Returns: the total number of bytes read
|
||||
// into the buffer, or -1 if there is no more data because the end of the file
|
||||
// has been reached.
|
||||
int FileInputStream::read(byteArray b) {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesRead =
|
||||
std::fread(b.data, 1, b.length, m_fileHandle);
|
||||
|
||||
if (std::ferror(m_fileHandle) != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
app.FatalLoadError();
|
||||
// return -1;
|
||||
} else if (numberOfBytesRead == 0) {
|
||||
// File pointer is past the end of the file
|
||||
return -1;
|
||||
}
|
||||
|
||||
return numberOfBytesRead;
|
||||
}
|
||||
|
||||
// Reads up to len bytes of data from this input stream into an array of bytes.
|
||||
// If len is not zero, the method blocks until some input is available;
|
||||
// otherwise, no bytes are read and 0 is returned. Parameters: b - the buffer
|
||||
// into which the data is read. off - the start offset in the destination array
|
||||
// b len - the maximum number of bytes read. Returns: the total number of bytes
|
||||
// read into the buffer, or -1 if there is no more data because the end of the
|
||||
// file has been reached.
|
||||
int FileInputStream::read(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
// 4J Stu - We don't want to read any more than the array buffer can hold
|
||||
assert(length <= (b.length - offset));
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesRead =
|
||||
std::fread(&b[offset], 1, length, m_fileHandle);
|
||||
|
||||
if (std::ferror(m_fileHandle) != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
app.FatalLoadError();
|
||||
// return -1;
|
||||
} else if (numberOfBytesRead == 0) {
|
||||
// File pointer is past the end of the file
|
||||
return -1;
|
||||
}
|
||||
|
||||
return numberOfBytesRead;
|
||||
}
|
||||
|
||||
// Closes this file input stream and releases any system resources associated
|
||||
// with the stream. If this stream has an associated channel then the channel is
|
||||
// closed as well.
|
||||
void FileInputStream::close() {
|
||||
if (m_fileHandle == nullptr) {
|
||||
// printf("\n\nFileInputStream::close - TRYING TO CLOSE AN INVALID FILE
|
||||
// void*\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int result = std::fclose(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
}
|
||||
|
||||
// Stop the dtor from trying to close it again
|
||||
m_fileHandle = nullptr;
|
||||
}
|
||||
|
||||
// Skips n bytes of input from this input stream. Fewer bytes might be skipped
|
||||
// if the end of the input stream is reached. The actual number k of bytes to be
|
||||
// skipped is equal to the smaller of n and count-pos. The value k is added into
|
||||
// pos and k is returned. Overrides: skip in class InputStream Parameters: n -
|
||||
// the number of bytes to be skipped. Returns: the actual number of bytes
|
||||
// skipped.
|
||||
int64_t FileInputStream::skip(int64_t n) {
|
||||
if (m_fileHandle == nullptr || n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64_t start = FileTell(m_fileHandle);
|
||||
if (start < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FileSeek(m_fileHandle, 0, SEEK_END)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64_t end = FileTell(m_fileHandle);
|
||||
if (end < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64_t offset = std::min(n, std::max<int64_t>(0, end - start));
|
||||
const int64_t target = start + offset;
|
||||
if (!FileSeek(m_fileHandle, target, SEEK_SET)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard library class
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "InputStream.h"
|
||||
|
||||
class File;
|
||||
|
||||
class FileInputStream : public InputStream {
|
||||
public:
|
||||
FileInputStream(const File& file);
|
||||
virtual ~FileInputStream();
|
||||
virtual int read();
|
||||
virtual int read(byteArray b);
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual int64_t skip(int64_t n);
|
||||
|
||||
private:
|
||||
std::FILE* m_fileHandle;
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
#include "../File.h"
|
||||
#include "FileOutputStream.h"
|
||||
|
||||
// Creates a file output stream to write to the file represented by the
|
||||
// specified File object. A new FileDescriptor object is created to represent
|
||||
// this file connection. First, if there is a security manager, its checkWrite
|
||||
// method is called with the path represented by the file argument as its
|
||||
// argument.
|
||||
//
|
||||
// If the file exists but is a directory rather than a regular file, does not
|
||||
// exist but cannot be created, or cannot be opened for any other reason then a
|
||||
// FileNotFoundException is thrown.
|
||||
//
|
||||
// Parameters:
|
||||
// file - the file to be opened for writing.
|
||||
FileOutputStream::FileOutputStream(const File& file) : m_fileHandle(nullptr) {
|
||||
if (file.exists() && file.isDirectory()) {
|
||||
// TODO 4J Stu - FileNotFoundException
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
m_fileHandle = _wfopen(file.getPath().c_str(), L"wb");
|
||||
#else
|
||||
const std::string nativePath = wstringtofilename(file.getPath());
|
||||
m_fileHandle = std::fopen(nativePath.c_str(), "wb");
|
||||
#endif
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
// TODO 4J Stu - Any form of error/exception handling
|
||||
perror("FileOutputStream::FileOutputStream");
|
||||
}
|
||||
}
|
||||
|
||||
FileOutputStream::~FileOutputStream() {
|
||||
if (m_fileHandle != nullptr) {
|
||||
std::fclose(m_fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Writes the specified byte to this file output stream. Implements the write
|
||||
// method of OutputStream. Parameters: b - the byte to be written.
|
||||
void FileOutputStream::write(unsigned int b) {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::uint8_t value = (std::uint8_t)b;
|
||||
const size_t numberOfBytesWritten = std::fwrite(&value, 1, 1, m_fileHandle);
|
||||
const int result = std::ferror(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
} else if (numberOfBytesWritten == 0) {
|
||||
// File pointer is past the end of the file
|
||||
}
|
||||
}
|
||||
|
||||
// Writes b.length bytes from the specified byte array to this file output
|
||||
// stream. Parameters: b - the data.
|
||||
void FileOutputStream::write(byteArray b) {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesWritten =
|
||||
std::fwrite(b.data, 1, b.length, m_fileHandle);
|
||||
const int result = std::ferror(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
} else if (numberOfBytesWritten == 0 || numberOfBytesWritten != b.length) {
|
||||
// File pointer is past the end of the file
|
||||
}
|
||||
}
|
||||
|
||||
// Writes len bytes from the specified byte array starting at offset off to this
|
||||
// file output stream. Parameters: b - the data. off - the start offset in the
|
||||
// data. len - the number of bytes to write.
|
||||
void FileOutputStream::write(byteArray b, unsigned int offset,
|
||||
unsigned int length) {
|
||||
// 4J Stu - We don't want to write any more than the array buffer holds
|
||||
assert(length <= (b.length - offset));
|
||||
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t numberOfBytesWritten =
|
||||
std::fwrite(&b[offset], 1, length, m_fileHandle);
|
||||
const int result = std::ferror(m_fileHandle);
|
||||
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
} else if (numberOfBytesWritten == 0 || numberOfBytesWritten != length) {
|
||||
// File pointer is past the end of the file
|
||||
}
|
||||
}
|
||||
//
|
||||
// Closes this file output stream and releases any system resources associated
|
||||
// with this stream. This file output stream may no longer be used for writing
|
||||
// bytes. If this stream has an associated channel then the channel is closed as
|
||||
// well.
|
||||
void FileOutputStream::close() {
|
||||
if (m_fileHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int result = std::fclose(m_fileHandle);
|
||||
if (result != 0) {
|
||||
// TODO 4J Stu - Some kind of error handling
|
||||
}
|
||||
|
||||
// Stop the dtor from trying to close it again
|
||||
m_fileHandle = nullptr;
|
||||
}
|
||||
|
||||
void FileOutputStream::flush() {
|
||||
if (m_fileHandle != nullptr) {
|
||||
std::fflush(m_fileHandle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard lib abstract
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "OutputStream.h"
|
||||
|
||||
class File;
|
||||
|
||||
class FileOutputStream : public OutputStream {
|
||||
public:
|
||||
FileOutputStream(const File& file);
|
||||
virtual ~FileOutputStream();
|
||||
virtual void write(unsigned int b);
|
||||
virtual void write(byteArray b);
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length);
|
||||
virtual void close();
|
||||
virtual void flush();
|
||||
|
||||
private:
|
||||
std::FILE* m_fileHandle;
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
// 4J Stu - We are not using GZIP compression, so this is just a pass through
|
||||
// class
|
||||
|
||||
#include "InputStream.h"
|
||||
|
||||
class GZIPInputStream : public InputStream {
|
||||
private:
|
||||
InputStream* stream;
|
||||
|
||||
public:
|
||||
GZIPInputStream(InputStream* out) : stream(out) {};
|
||||
virtual int read() { return stream->read(); };
|
||||
virtual int read(byteArray b) { return stream->read(b); };
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length) {
|
||||
return stream->read(b, offset, length);
|
||||
};
|
||||
virtual void close() { return stream->close(); };
|
||||
virtual int64_t skip(int64_t n) { return 0; };
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
// 4J Stu - We are not using GZIP compression, so this is just a pass through
|
||||
// class
|
||||
|
||||
#include "OutputStream.h"
|
||||
|
||||
class GZIPOutputStream : public OutputStream {
|
||||
private:
|
||||
OutputStream* stream;
|
||||
|
||||
public:
|
||||
GZIPOutputStream(OutputStream* out) : stream(out) {};
|
||||
virtual void write(unsigned int b) { stream->write(b); };
|
||||
virtual void write(byteArray b) { stream->write(b); };
|
||||
virtual void write(byteArray b, unsigned int offset, unsigned int length) {
|
||||
stream->write(b, offset, length);
|
||||
};
|
||||
virtual void close() { stream->close(); };
|
||||
virtual void flush() {}
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputStream.h"
|
||||
#include "ByteArrayInputStream.h"
|
||||
#include "DataInput.h"
|
||||
#include "DataInputStream.h"
|
||||
#include "FileInputStream.h"
|
||||
#include "GZIPInputStream.h"
|
||||
|
||||
#include "OutputStream.h"
|
||||
#include "ByteArrayOutputStream.h"
|
||||
#include "DataOutput.h"
|
||||
#include "BufferedOutputStream.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "FileOutputStream.h"
|
||||
#include "GZIPOutputStream.h"
|
||||
|
||||
#include "Reader.h"
|
||||
#include "BufferedReader.h"
|
||||
#include "InputStreamReader.h"
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
#include "../File.h"
|
||||
#include "InputOutputStream.h"
|
||||
#include "InputStream.h"
|
||||
|
||||
InputStream* InputStream::getResourceAsStream(const std::wstring& fileName) {
|
||||
File file(fileName);
|
||||
return file.exists() ? new FileInputStream(file) : nullptr;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
// 4J Stu - Represents Java standard lib abstract
|
||||
|
||||
class InputStream {
|
||||
public:
|
||||
virtual ~InputStream() {}
|
||||
|
||||
virtual int read() = 0;
|
||||
virtual int read(byteArray b) = 0;
|
||||
virtual int read(byteArray b, unsigned int offset, unsigned int length) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual int64_t skip(int64_t n) = 0;
|
||||
|
||||
static InputStream* getResourceAsStream(const std::wstring& fileName);
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "../../Header Files/stdafx.h"
|
||||
|
||||
#include "InputStream.h"
|
||||
#include "DataInputStream.h"
|
||||
#include "InputStreamReader.h"
|
||||
|
||||
// Creates an InputStreamReader that uses the default charset.
|
||||
// Parameters:
|
||||
// in - An InputStream
|
||||
InputStreamReader::InputStreamReader(InputStream* in)
|
||||
: stream(new DataInputStream(in)) {}
|
||||
|
||||
// Closes the stream and releases any system resources associated with it.
|
||||
// Once the stream has been closed, further read(), ready(), mark(), reset(), or
|
||||
// skip() invocations will throw an IOException. Closing a previously closed
|
||||
// stream has no effect.
|
||||
void InputStreamReader::close() { stream->close(); }
|
||||
|
||||
// Reads a single character.
|
||||
// Returns:
|
||||
// The character read, or -1 if the end of the stream has been reached
|
||||
int InputStreamReader::read() { return stream->readUTFChar(); }
|
||||
|
||||
// Reads characters into a portion of an array.
|
||||
// Parameters:
|
||||
// cbuf - Destination buffer
|
||||
// offset - Offset at which to start storing characters
|
||||
// length - Maximum number of characters to read
|
||||
// Returns:
|
||||
// The number of characters read, or -1 if the end of the stream has been
|
||||
// reached
|
||||
int InputStreamReader::read(wchar_t cbuf[], unsigned int offset,
|
||||
unsigned int length) {
|
||||
unsigned int charsRead = 0;
|
||||
for (unsigned int i = offset; i < offset + length; i++) {
|
||||
wchar_t value = (wchar_t)stream->readUTFChar();
|
||||
if (value != -1) {
|
||||
cbuf[i] = value;
|
||||
charsRead++;
|
||||
}
|
||||
// TODO 4J Stu - The read might throw an exception? In which case we
|
||||
// should return -1
|
||||
else
|
||||
break;
|
||||
}
|
||||
return charsRead;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
class InputStream;
|
||||
|
||||
class InputStreamReader : public Reader {
|
||||
private:
|
||||
DataInputStream* stream;
|
||||
|
||||
public:
|
||||
InputStreamReader(InputStream* in);
|
||||
|
||||
virtual void close();
|
||||
virtual int read();
|
||||
virtual int read(wchar_t cbuf[], unsigned int offset, unsigned int length);
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
// 4J Stu - Represents Java standard lib abstract
|
||||
|
||||
class OutputStream {
|
||||
public:
|
||||
virtual ~OutputStream() {}
|
||||
|
||||
virtual void write(unsigned int b) = 0;
|
||||
virtual void write(byteArray b) = 0;
|
||||
virtual void write(byteArray b, unsigned int offset,
|
||||
unsigned int length) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual void flush() = 0;
|
||||
};
|
||||
13
Minecraft.World/ConsoleJavaLibs/InputOutputStream/Reader.h
Normal file
13
Minecraft.World/ConsoleJavaLibs/InputOutputStream/Reader.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
virtual ~Reader() {}
|
||||
|
||||
virtual void close() = 0; // Closes the stream and releases any system
|
||||
// resources associated with it.
|
||||
virtual int read() = 0; // Reads a single character.
|
||||
virtual int read(
|
||||
wchar_t cbuf[], unsigned int off,
|
||||
unsigned int len) = 0; // Reads characters into a portion of an array.
|
||||
};
|
||||
Reference in New Issue
Block a user