2022-06-27 11:46:13 +02:00
// Copyright 2022, FOSS-VG Developers and Contributers
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
2022-06-24 12:15:34 +02:00
// information taken from https://wiki.vg/NBT
// This is an attempt at creating a uniform model for all NBT tags to allow for a uniform interface based on subclassing a single NBT tag super class.
2022-06-25 13:37:57 +02:00
// 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.
2022-06-24 12:15:34 +02:00
// All tag types:
2022-10-02 07:39:28 +02:00
// Generic: Tag(uint8:tag_type, String:name, uint16:name_size, byte[]:content, int32:size)
// End: Tag( 0, "", 0, None, 0) => used to determine the end of a compound tag, only the type gets 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
// Float: Tag( 5, String:name, uint16:name_size, float:content, 4) => 32 bit IEEE754 floating point number, size not stored
// Double: Tag( 6, String:name, uint16:name_size, double:content, 8) => 64 bit IEEE754 floating point number, size not stored
// Int8Array: Tag( 7, String:name, uint16:name_size, int8[]:content, int32:length) => 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
// List: Tag<Tag:type>( 9, String:name, uint16:name_size, Tag[]:content, int32:length) => list of tags of the same type with tag type and name information omitted prefixed by (in order) content type and length
// Compound: Tag(10, String:name, uint16:name_size, Tag[]:content, int32:length) => list of tags, last tag is always an end tag, size not stored
// Int32Array: Tag(11, String:name, uint16:name_size, int32[]:content,int32:length) => list of 32 bit signed integers prefixed with its size
// Int64Array: Tag(12, String:name, uint16:name_size, int64[]:content,int32:length) => list of 64 bit signed integers prefixed with its size
2022-06-27 04:50:32 +02:00
# pragma once
# include <cstdint>
# include <vector>
2022-07-20 08:38:04 +02:00
# include <tinyutf8/tinyutf8.h>
2022-09-26 03:11:44 +02:00
# include <mutex>
2022-08-02 03:35:08 +02:00
# include "error.hpp"
2022-06-27 04:50:32 +02:00
namespace NBT {
2022-09-15 02:00:07 +02:00
namespace Helper {
2022-06-28 16:51:52 +02:00
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 ) ;
2022-08-04 07:42:40 +02:00
ErrorOr < float > readFloat ( uint8_t data [ ] , uint64_t dataSize , uint64_t currentPosition ) ;
ErrorOr < double > readDouble ( uint8_t data [ ] , uint64_t dataSize , uint64_t currentPosition ) ;
2022-06-28 16:51:52 +02:00
ErrorOr < std : : vector < int8_t > > readInt8Array ( uint8_t data [ ] , uint64_t dataSize , uint64_t currentPosition ) ;
2022-07-20 08:38:04 +02:00
ErrorOr < tiny_utf8 : : string > readString ( uint8_t data [ ] , uint64_t dataSize , uint64_t currentPosition ) ;
2022-06-28 16:51:52 +02:00
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 ) ;
2022-07-02 02:08:32 +02:00
void writeInt8 ( std : : vector < uint8_t > * destination , int8_t data ) ;
void writeInt16 ( std : : vector < uint8_t > * destination , int16_t data ) ;
void writeInt32 ( std : : vector < uint8_t > * destination , int32_t data ) ;
void writeInt64 ( std : : vector < uint8_t > * destination , int64_t data ) ;
2022-08-04 07:42:40 +02:00
void writeFloat ( std : : vector < uint8_t > * destination , float data ) ;
void writeDouble ( std : : vector < uint8_t > * destination , double data ) ;
2022-07-02 02:08:32 +02:00
void writeInt8Array ( std : : vector < uint8_t > * destination , std : : vector < int8_t > data ) ;
2022-07-06 12:57:32 +02:00
void writeInt8Array ( std : : vector < uint8_t > * destination , int8_t data [ ] , uint32_t dataSize ) ;
2022-09-26 03:11:44 +02:00
ErrorOrVoid writeString ( std : : vector < uint8_t > * destination , tiny_utf8 : : string data ) ;
2022-07-02 02:08:32 +02:00
void writeInt32Array ( std : : vector < uint8_t > * destination , std : : vector < int32_t > data ) ;
2022-07-06 14:58:02 +02:00
void writeInt32Array ( std : : vector < uint8_t > * destination , int32_t data [ ] , uint32_t dataSize ) ;
2022-07-02 02:08:32 +02:00
void writeInt64Array ( std : : vector < uint8_t > * destination , std : : vector < int64_t > data ) ;
2022-07-06 14:58:02 +02:00
void writeInt64Array ( std : : vector < uint8_t > * destination , int64_t data [ ] , uint32_t dataSize ) ;
2022-08-11 07:43:54 +02:00
2022-08-13 15:56:59 +02:00
ErrorOr < uint64_t > totalTagSize ( uint8_t data [ ] , uint64_t dataSize , uint64_t currentPosition ) ;
ErrorOr < int32_t > containedDataLength ( uint8_t data [ ] , uint64_t dataSize , uint64_t currentPosition ) ;
2022-06-28 15:19:47 +02:00
}
2022-08-08 14:17:35 +02:00
namespace TagType {
2022-09-15 06:06:47 +02:00
const uint8_t END = 0 ;
const uint8_t INT8 = 1 ;
const uint8_t INT16 = 2 ;
const uint8_t INT32 = 3 ;
const uint8_t INT64 = 4 ;
const uint8_t FLOAT = 5 ;
const uint8_t DOUBLE = 6 ;
const uint8_t INT8_ARRAY = 7 ;
const uint8_t STRING = 8 ;
const uint8_t LIST = 9 ;
const uint8_t COMPOUND = 10 ;
const uint8_t INT32_ARRAY = 11 ;
const uint8_t INT64_ARRAY = 12 ;
// This is a workaround that's not part of the spec.
const uint8_t INVALID = 255 ;
2022-08-08 14:17:35 +02:00
}
2022-09-26 03:11:44 +02:00
namespace Tag {
class Generic {
protected :
std : : mutex mutex ;
uint8_t type ;
public :
tiny_utf8 : : string name ;
Generic ( ) ;
virtual ~ Generic ( ) ;
2022-10-02 07:25:50 +02:00
virtual ErrorOrVoid serialize ( std : : vector < uint8_t > * rawData ) ;
virtual ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) ;
2022-09-26 03:11:44 +02:00
uint8_t getTagType ( ) ;
} ;
class End : public Generic {
public :
End ( ) ;
2022-10-02 07:25:50 +02:00
// This needs a separate serializer because
// END tags have a special header.
2022-10-06 11:09:58 +02:00
ErrorOrVoid serialize ( std : : vector < uint8_t > * rawData ) override ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-26 03:11:44 +02:00
} ;
class Int8 : public Generic {
private :
int8_t value ;
public :
Int8 ( ) ;
Int8 ( tiny_utf8 : : string name , int8_t value ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-26 03:11:44 +02:00
int8_t getValue ( ) ;
void setValue ( int8_t value ) ;
} ;
class Int16 : public Generic {
private :
int16_t value ;
public :
Int16 ( ) ;
Int16 ( tiny_utf8 : : string name , int16_t value ) ;
2022-08-03 20:31:12 +02:00
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-26 03:11:44 +02:00
int16_t getValue ( ) ;
void setValue ( int16_t value ) ;
} ;
class Int32 : public Generic {
private :
int32_t value ;
public :
Int32 ( ) ;
Int32 ( tiny_utf8 : : string name , int32_t value ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-26 03:11:44 +02:00
int32_t getValue ( ) ;
void setValue ( int32_t value ) ;
} ;
class Int64 : public Generic {
private :
int64_t value ;
public :
Int64 ( ) ;
Int64 ( tiny_utf8 : : string name , int64_t value ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-26 03:11:44 +02:00
int64_t getValue ( ) ;
void setValue ( int64_t value ) ;
} ;
class Float : public Generic {
private :
float value ;
public :
Float ( ) ;
Float ( tiny_utf8 : : string name , float value ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-26 03:11:44 +02:00
float getValue ( ) ;
void setValue ( float value ) ;
} ;
class Double : public Generic {
private :
double value ;
public :
Double ( ) ;
Double ( tiny_utf8 : : string name , double value ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-26 03:11:44 +02:00
double getValue ( ) ;
void setValue ( double value ) ;
} ;
2022-09-28 03:43:54 +02:00
class Int8Array : public Generic {
private :
std : : vector < int8_t > data ;
public :
Int8Array ( ) ;
Int8Array ( tiny_utf8 : : string name , std : : vector < int8_t > data ) ;
Int8Array ( tiny_utf8 : : string name , uint64_t length , int8_t data [ ] ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-28 03:43:54 +02:00
std : : vector < int8_t > getData ( ) ;
ErrorOr < int8_t > getValue ( uint64_t position ) ;
void setData ( std : : vector < int8_t > newData ) ;
ErrorOrVoid setValue ( uint64_t position , int8_t value ) ;
uint64_t length ( ) ;
void addElement ( int8_t element ) ;
ErrorOrVoid removeElement ( uint64_t position ) ;
} ;
class String : public Generic {
private :
tiny_utf8 : : string value ;
public :
String ( ) ;
String ( tiny_utf8 : : string name , tiny_utf8 : : string value ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-28 03:43:54 +02:00
tiny_utf8 : : string getValue ( ) ;
void setValue ( tiny_utf8 : : string value ) ;
} ;
class List : public Generic {
private :
std : : vector < Generic * > tags ;
2022-10-01 04:51:53 +02:00
uint8_t containedType ;
2022-09-28 03:43:54 +02:00
public :
List ( ) ;
List ( tiny_utf8 : : string name , uint8_t type ) ;
List ( tiny_utf8 : : string name , std : : vector < Generic * > data ) ;
~ List ( ) override ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-28 03:43:54 +02:00
ErrorOr < Generic * > getElementPointer ( uint64_t position ) ;
2022-10-04 02:39:58 +02:00
ErrorOrVoid setElementPointerAt ( uint64_t position , Generic * pointer ) ;
ErrorOrVoid appendPointer ( Generic * pointer ) ;
2022-09-28 03:43:54 +02:00
ErrorOrVoid deleteElement ( uint64_t position ) ;
uint64_t length ( ) ;
} ;
class Compound : public Generic {
private :
std : : vector < Generic * > tags ;
2022-10-14 18:08:49 +02:00
// built-in end tag
End * endPointer ;
2022-09-28 03:43:54 +02:00
public :
Compound ( ) ;
Compound ( tiny_utf8 : : string name ) ;
Compound ( tiny_utf8 : : string name , std : : vector < Generic * > data ) ;
~ Compound ( ) override ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-28 03:43:54 +02:00
ErrorOr < Generic * > getElementPointer ( uint64_t position ) ;
2022-10-05 01:12:38 +02:00
ErrorOrVoid setElementPointerAt ( uint64_t position , Generic * pointer ) ;
2022-10-14 18:30:39 +02:00
ErrorOrVoid appendPointer ( Generic * pointer ) ;
2022-09-28 03:43:54 +02:00
ErrorOrVoid deleteElement ( uint64_t position ) ;
uint64_t length ( ) ;
} ;
class Int32Array : public Generic {
private :
std : : vector < int32_t > data ;
public :
Int32Array ( ) ;
Int32Array ( tiny_utf8 : : string name , std : : vector < int32_t > data ) ;
Int32Array ( tiny_utf8 : : string name , uint64_t length , int32_t data [ ] ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-28 03:43:54 +02:00
std : : vector < int32_t > getData ( ) ;
ErrorOr < int32_t > getValue ( uint64_t position ) ;
void setData ( std : : vector < int32_t > newData ) ;
ErrorOrVoid setValue ( uint64_t position , int32_t value ) ;
uint64_t length ( ) ;
void addElement ( int32_t element ) ;
ErrorOrVoid removeElement ( uint64_t position ) ;
} ;
class Int64Array : public Generic {
private :
std : : vector < int64_t > data ;
public :
Int64Array ( ) ;
Int64Array ( tiny_utf8 : : string name , std : : vector < int64_t > data ) ;
Int64Array ( tiny_utf8 : : string name , uint64_t length , int64_t data [ ] ) ;
2022-10-02 07:25:50 +02:00
ErrorOrVoid serializeWithoutHeader ( std : : vector < uint8_t > * rawData ) override ;
2022-09-28 03:43:54 +02:00
std : : vector < int64_t > getData ( ) ;
ErrorOr < int64_t > getValue ( uint64_t position ) ;
void setData ( std : : vector < int64_t > newData ) ;
ErrorOrVoid setValue ( uint64_t position , int64_t value ) ;
uint64_t length ( ) ;
void addElement ( int64_t element ) ;
ErrorOrVoid removeElement ( uint64_t position ) ;
} ;
2022-09-26 03:11:44 +02:00
}
2022-08-03 20:31:12 +02:00
2022-10-15 23:05:26 +02:00
ErrorOr < std : : vector < Tag : : Generic * > > deserialize ( uint8_t data [ ] , uint64_t dataSize , uint64_t initialPosition = 0 , uint64_t * processedDataSize = nullptr ) ;
2022-08-15 09:53:06 +02:00
bool validateRawNBTData ( uint8_t data [ ] , uint64_t dataSize , uint64_t initialPosition = 0 , uint64_t * processedDataSize = nullptr ) ;
2022-06-27 04:50:32 +02:00
}