I'm adding a makefile
BodgeMaster-unfinished
Gregory Powers 2022-06-28 10:44:32 -04:00
commit ae65968f98
5 changed files with 80 additions and 13 deletions

View File

@ -5,6 +5,10 @@ the GNU AGPL version 3. A copy of the license has been provided to you
as `LICENSE.md` in the base directory of the repository or source tree.
It is also available at `https://www.gnu.org/licenses/agpl-3.0.en.html`.
This software is distributed WITHOUT ANY WARRANTY (without even the
implied warranty of merchantability or fitness for any particular purpose)
as specified by the AGPL.
People who have contributed to this project:
Jan Danielzick (aka. BodgeMaster)
Milan Suman (aka. Shwoomple)

View File

@ -42,7 +42,8 @@ all uppercase letters and underscores for their names.
Variables and functions start with a lowercase letter, classes and structs
with an uppercase letter.
Avoid abbreviations unless they are well known and universally used acronyms.
Avoid abbreviations unless they are well known acronyms and/or
universally used.
Use explicitly sized data types where possible.
For example, use `int32_t` instead of `int`.

View File

@ -15,22 +15,59 @@
#pragma once
#include <cstdint>
template <typename T>
struct ErrorOr {
bool isError;
uint8_t errorCode;
T value;
ErrorOr<T>();
ErrorOr<T>(T);
ErrorOr<T>(bool);
ErrorOr<T>(bool, uint8_t);
ErrorOr<T>(bool, uint8_t, T);
};
template <typename T>
ErrorOr<T>::ErrorOr() {
this->isError = false;
this->errorCode = 0;
}
template <typename T>
ErrorOr<T>::ErrorOr(T value) {
this->isError = false;
this->errorCode = 0;
this->value = value;
}
template <typename T>
ErrorOr<T>::ErrorOr(bool isError) {
this->isError = isError;
this->errorCode = 0;
}
template <typename T>
ErrorOr<T>::ErrorOr(bool isError, uint8_t errorCode) {
this->isError = isError;
this->errorCode = errorCode;
}
template <typename T>
ErrorOr<T>::ErrorOr(bool isError, uint8_t errorCode, T value) {
this->isError = isError;
this->errorCode = errorCode;
this->value = value;
}
namespace ErrorCodes {
// These are all arbitrary values used to assign error codes to different
// kinds of errors.
// Using them is optional as ErrorOr<> accepts any uint8_t value as
// error code, but they are useful for readability.
// IndexOutOfRangeException equivalent
const uint8_t RANGE_ERROR = 1;
}

View File

@ -42,25 +42,25 @@ int endianness_example() {
}
namespace NBT {
namespace helpers {
ErrorOr<int8_t> readByte(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition) {
namespace helper {
ErrorOr<int8_t> readInt8(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition) {
//TODO: implement
return ErrorOr<int8_t>(0);
return ErrorOr<int8_t>((int8_t) 0);
}
ErrorOr<int16_t> readInt16(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition) {
//TODO: implement
return ErrorOr<int16_t>(0);
return ErrorOr<int16_t>((int16_t) 0);
}
ErrorOr<int32_t> readInt32(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition) {
//TODO: implement
return ErrorOr<int32_t>(0);
return ErrorOr<int32_t>((int32_t) 0);
}
ErrorOr<int64_t> readInt64(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition) {
//TODO: implement
return ErrorOr<int64_t>(0);
return ErrorOr<int64_t>((int64_t) 0);
}
//FIXME: we just assume that float is a single-precision IEEE754
@ -81,12 +81,11 @@ namespace NBT {
return ErrorOr<double>(0.0);
}
ErrorOr<std::vector<int8_t>> readByteArray(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition) {
ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition) {
//TODO: implement
return ErrorOr<std::vector<int8_t>>({0});
}
//TODO: find suitable string type
// Maybe use a struct that holds decoded (de-Java-fied) string
// data, decoded size, and original size? Original size is needed
// so the parser knows where to continue.

View File

@ -19,16 +19,16 @@
// NBT tags have a type, optionally a name which consists of the name size and the name string, optionally content type, and optionally a payload which can consist of optionally content type, optionally a content size,
// and the stored content. The format in which they are stored is as follows: <type><name size><name><payload>. All numbers are stored in big endian representation.
// All tag types:
// generic representation: Tag(Byte:tag_type, String:name, uint16:name_size, byte[]:content, int32:size)
// generic representation: Tag(uint8:tag_type, String:name, uint16:name_size, byte[]:content, int32:size)
// None (compound end): Tag( 0, "", 0, None, 0) => used to determine the end of a compound tag, only the type gets stored
// byte: Tag( 1, String:name, uint16:name_size, byte:content, 1) => a single signed byte, size not stored
// int8: Tag( 1, String:name, uint16:name_size, int8:content, 1) => a single signed byte, size not stored
// int16: Tag( 2, String:name, uint16:name_size, int16:content, 2) => 16 bit signed integer, size not stored
// int32: Tag( 3, String:name, uint16:name_size, int32:content, 4) => 32 bit signed integer, size not stored
// int64: Tag( 4, String:name, uint16:name_size, int64:content, 8) => 64 bit signed integer, size not stored
// float32: Tag( 5, String:name, uint16:name_size, float32:content,4) => 32 bit IEEE754 floating point number, size not stored
// float64: Tag( 6, String:name, uint16:name_size, float64:content,8) => 64 bit IEEE754 floating point number, size not stored
// byte[]: Tag( 7, String:name, uint16:name_size, byte[]:content, int32:size) => content stored prefixed with size
// String: Tag( 8, String:name, uint16:name_size, byte[]:content, uint16:size) => Java style modified UTF-8 string, content stored prefixed with size
// int8[]: Tag( 7, String:name, uint16:name_size, int8[]:content, int32:size) => content stored prefixed with size
// String: Tag( 8, String:name, uint16:name_size, String:content, uint16:size) => Java style modified UTF-8 string, content stored prefixed with size
// Tag[] (list): Tag<Tag:type>( 9, String:name, uint16:name_size, Tag[]:content, int32:size) => list of tags of the same type with tag type and name information omitted prefixed by (in order) content type and size
// Tag[] (compound): Tag(10, String:name, uint16:name_size, Tag[]:content, int32:size) => list of tags, last tag is always an end tag, size not stored
// int32[]: Tag(11, String:name, uint16:name_size, int32[]:content,int32:size) => list of 32 bit signed integers prefixed with its size, endianness not verified at this point
@ -40,5 +40,31 @@
#include "error.h++"
namespace NBT {
namespace helper {
ErrorOr<int8_t> readInt8(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<int16_t> readInt16(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<int32_t> readInt32(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<int64_t> readInt64(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
//FIXME: we just assume that float is a single-precision IEEE754
// floating point number
ErrorOr<float> readFloat32(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
//FIXME: we just assume that double is a double-precision IEEE754
// floating point number
ErrorOr<double> readFloat64(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
//ErrorOr<> readString(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int32_t>> readInt32Array(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int64_t>> readInt64Array(uint8_t* data[], uint64_t dataSize, uint64_t currentPosition);
}
bool validateRawNBTData(uint8_t* data[], int length);
}