Rewriting NBT

- Namespace
- Separate payload from tag itself
- Group numerics types with template
master
Julien Rosset 5 years ago
parent 9850b9a3c4
commit 479fe96cf2

@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.16)
project(NBTModifier)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
@ -21,16 +22,7 @@ add_executable(
icons/breeze.qrc icons/breeze-dark.qrc
NBT/AbstractTag.h NBT/AbstractTag.cpp
NBT/AbstractNamedTag.h NBT/AbstractNamedTag.cpp
NBT/TagEnd.cpp NBT/TagEnd.h
NBT/TagByte.cpp NBT/TagByte.h
NBT/TagShort.cpp NBT/TagShort.h
NBT/TagInt.cpp NBT/TagInt.h
NBT/TagLong.cpp NBT/TagLong.h
NBT/TagFloat.cpp NBT/TagFloat.h
NBT/TagDouble.cpp NBT/TagDouble.h
NBT/TagByteArray.cpp NBT/TagByteArray.h
NBT/TagString.cpp NBT/TagString.h
NBT/Payload/IPayload.h NBT/Payload/IPayload.cpp
NBT/Payload/AbstractNumeric.h
)
target_link_libraries(NBTModifier Qt5::Widgets Qt5::Svg)

@ -1,75 +0,0 @@
#include "AbstractTag.h"
#include "TagEnd.h"
#include "TagByte.h"
#include "TagShort.h"
#include "TagInt.h"
#include "TagLong.h"
#include "TagFloat.h"
#include "TagDouble.h"
#include "TagByteArray.h"
#include "TagString.h"
#include <QtCore/QDataStream>
AbstractTag::AbstractTag (const quint8 id) : m_id(id) {}
const quint8 AbstractTag::id () const {
return m_id;
}
const quint8 AbstractTag::extractId (const QByteArray &data) {
QDataStream stream(data);
quint8 id;
stream >> id;
return id;
}
AbstractTag *AbstractTag::extractEmptyTag (const QByteArray &data) {
switch (extractId(data)) {
case TagEnd::ID:
return new TagEnd();
case TagByte::ID:
return new TagByte();
case TagShort::ID:
return new TagShort();
case TagInt::ID:
return new TagInt();
case TagLong::ID:
return new TagLong();
case TagFloat::ID:
return new TagFloat();
case TagDouble::ID:
return new TagDouble();
case TagByteArray::ID:
return new TagByteArray();
case TagString::ID:
return new TagString();
}
return nullptr;
}
QDataStream &operator << (QDataStream &data, const AbstractTag &tag) {
data << tag.id();
tag.writeToData(data);
return data;
}
QDataStream &operator >> (QDataStream &data, AbstractTag &tag) {
quint8 id;
data >> id;
tag.readFromData(data);
return data;
}

@ -1,55 +0,0 @@
#ifndef NBTMODIFIER_ABSTRACTTAG_H
#define NBTMODIFIER_ABSTRACTTAG_H
#include <QtGlobal>
class QDataStream;
/**
* Interface for all NBT tags
*/
class AbstractTag {
public:
virtual inline ~AbstractTag () {};
const quint8 id () const;
static const quint8 extractId (const QByteArray &data);
static AbstractTag *extractEmptyTag (const QByteArray &data);
friend QDataStream &operator << (QDataStream &data, const AbstractTag &tag);
friend QDataStream &operator >> (QDataStream &data, AbstractTag &tag);
protected:
/**
* Create a new tag
*
* @param id
*/
explicit AbstractTag (const quint8 id);
/**
* Read a tag from a data stream
*
* @param data The data stream
*
* @return True if read is success, otherwise false
*/
virtual void readFromData (QDataStream &data) = 0;
/**
* Write a tag to a data stream
*
* @param data The data stream
*
* @return True if write is success, otherwise false
*/
virtual void writeToData (QDataStream &data) const = 0;
private:
/**
* The tag's ID
*/
const quint8 m_id;
};
#endif //NBTMODIFIER_ABSTRACTTAG_H

@ -0,0 +1,70 @@
#ifndef NBTMODIFIER_NBT_PAYLOAD_ABSTRACTNUMERIC_H
#define NBTMODIFIER_NBT_PAYLOAD_ABSTRACTNUMERIC_H
#include <QtCore/qpoint.h>
#include "IPayload.h"
namespace NBT {
namespace Payload {
/**
* NBT "numeric" payload (Byte, Short, Int, Long, Float, Double)
*/
template<typename T>
class AbstractNumeric : public IPayload {
static_assert(
std::is_same<T, qint8>::value
|| std::is_same<T, qint16>::value
|| std::is_same<T, qint32>::value
|| std::is_same<T, qint64>::value
|| std::is_same<T, float>::value
|| std::is_same<T, double>::value,
"The \"AbstractNumeric\" payload must be type of qint8 (Byte), qint16 (Short), qint32 (Int), qint64 (Long), float or double"
);
public:
/**
* New payload
*
* @param value The payload value
*/
AbstractNumeric (T const value = 0);
/**
* The payload value
*
* @return The payload value
*/
const T value () const;
/**
* Change the payload value
*
* @param value The new value
*/
void setValue (T const value);
virtual void readFromData (QDataStream &stream) override;
virtual void writeToData (QDataStream &stream) const override;
private:
T m_value;
};
#define IMPLEMENTS_ABSTRACTNUMERIC(className, templateType, id) class className : public AbstractNumeric<templateType> { virtual inline quint8 const ID () const override { return id; } };
IMPLEMENTS_ABSTRACTNUMERIC(Byte, qint8, 1)
IMPLEMENTS_ABSTRACTNUMERIC(Short, qint16, 2)
IMPLEMENTS_ABSTRACTNUMERIC(Int, qint32, 3)
IMPLEMENTS_ABSTRACTNUMERIC(Long, qint64, 4)
IMPLEMENTS_ABSTRACTNUMERIC(Float, float, 5)
IMPLEMENTS_ABSTRACTNUMERIC(Double, double, 6)
}
}
#include "AbstractNumeric.tpp"
#endif //NBTMODIFIER_NBT_PAYLOAD_ABSTRACTNUMERIC_H

@ -0,0 +1,27 @@
#include "AbstractNumeric.h"
#include <QtEndian>
#include <QtCore/QDataStream>
template<typename T>
NBT::Payload::AbstractNumeric<T>::AbstractNumeric (T const value): m_value(value) {
}
template<typename T>
const T NBT::Payload::AbstractNumeric<T>::value () const {
return m_value;
}
template<typename T>
void NBT::Payload::AbstractNumeric<T>::setValue (T const value) {
m_value = value;
}
template<typename T>
void NBT::Payload::AbstractNumeric<T>::readFromData (QDataStream &stream) {
stream >> m_value;
m_value = qFromBigEndian(m_value);
}
template<typename T>
void NBT::Payload::AbstractNumeric<T>::writeToData (QDataStream &stream) const {
stream << qToBigEndian(m_value);
}

@ -0,0 +1,12 @@
#include "IPayload.h"
#include <QtCore/QDataStream>
QDataStream &operator << (QDataStream &stream, const NBT::Payload::IPayload &payload) {
payload.writeToData(stream);
return stream;
}
QDataStream &operator >> (QDataStream &stream, NBT::Payload::IPayload &payload) {
payload.readFromData(stream);
return stream;
}

@ -0,0 +1,70 @@
#ifndef NBTMODIFIER_NBT_PAYLOAD_IPAYLOAD_H
#define NBTMODIFIER_NBT_PAYLOAD_IPAYLOAD_H
#define NBTMODIFIER_NBT_PAYLOAD_IPAYLOAD_H
#include <QtGlobal>
class QDataStream;
namespace NBT {
/**
* Namespace for all NBT payloads
*/
namespace Payload {
/**
* A NBT payload interface
*/
class IPayload {
public:
/**
* When a payload is destroyed
*/
virtual inline ~IPayload () {};
/**
* The NBT ID identifying the payload
*
* @return
*/
virtual quint8 const ID () const = 0;
/**
* Read a payload from a data stream
*
* @param stream The data stream
*/
virtual void readFromData (QDataStream &stream) = 0;
/**
* Write a payload to a data stream
*
* @param stream The data stream
*/
virtual void writeToData (QDataStream &stream) const = 0;
/**
* Convenient operator to read a payload from a data stream
*
* @param stream The data stream
* @param payload The payload
*
* @return The data stream (allow call chaining)
*
* @see readFromData
*/
friend QDataStream &operator >> (QDataStream &stream, IPayload &payload);
/**
* Convenient operator to write a payload to a data stream
*
* @param stream The data stream
* @param payload The payload
*
* @return The data stream (allow call chaining)
*
* @see writeToData
*/
friend QDataStream &operator << (QDataStream &stream, IPayload const &payload);
};
}
}
#endif //NBTMODIFIER_NBT_PAYLOAD_IPAYLOAD_H

@ -1,16 +0,0 @@
#include "TagByte.h"
#include <QtCore/QDataStream>
TagByte::TagByte (const qint8 value) : AbstractNamedTag(ID), m_value(value) {}
const qint8 TagByte::value () const {
return m_value;
}
void TagByte::readPayloadFromData (QDataStream &data) {
data >> m_value;
}
void TagByte::writePayloadToData (QDataStream &data) const {
data << m_value;
}

@ -1,22 +0,0 @@
#ifndef NBTMODIFIER_TAGBYTE_H
#define NBTMODIFIER_TAGBYTE_H
#include "AbstractNamedTag.h"
class TagByte : public AbstractNamedTag {
public:
static constexpr quint8 ID = 1;
TagByte (const qint8 value = 0);
const qint8 value () const;
protected:
virtual void readPayloadFromData (QDataStream &data) override;
virtual void writePayloadToData (QDataStream &data) const override;
private:
qint8 m_value;
};
#endif //NBTMODIFIER_TAGBYTE_H

@ -1,18 +0,0 @@
#include "TagDouble.h"
#include <QtEndian>
#include <QtCore/QDataStream>
TagDouble::TagDouble (const double value) : AbstractNamedTag(ID), m_value(value) {}
const double TagDouble::value () const {
return m_value;
}
void TagDouble::readPayloadFromData (QDataStream &data) {
data >> m_value;
m_value = qFromBigEndian(m_value);
}
void TagDouble::writePayloadToData (QDataStream &data) const {
data << qToBigEndian(m_value);
}

@ -1,22 +0,0 @@
#ifndef NBTMODIFIER_TAGDOUBLE_H
#define NBTMODIFIER_TAGDOUBLE_H
#include "AbstractNamedTag.h"
class TagDouble : public AbstractNamedTag {
public:
static constexpr quint8 ID = 6;
TagDouble (const double value = 0);
const double value () const;
protected:
virtual void readPayloadFromData (QDataStream &data) override;
virtual void writePayloadToData (QDataStream &data) const override;
private:
double m_value;
};
#endif //NBTMODIFIER_TAGDOUBLE_H

@ -1,18 +0,0 @@
#include "TagFloat.h"
#include <QtEndian>
#include <QtCore/QDataStream>
TagFloat::TagFloat (const float value) : AbstractNamedTag(ID), m_value(value) {}
const float TagFloat::value () const {
return m_value;
}
void TagFloat::readPayloadFromData (QDataStream &data) {
data >> m_value;
m_value = qFromBigEndian(m_value);
}
void TagFloat::writePayloadToData (QDataStream &data) const {
data << qToBigEndian(m_value);
}

@ -1,23 +0,0 @@
#ifndef NBTMODIFIER_TAGFLOAT_H
#define NBTMODIFIER_TAGFLOAT_H
#include <QtCore/qfloat16.h>
#include "AbstractNamedTag.h"
class TagFloat : public AbstractNamedTag {
public:
static constexpr quint8 ID = 5;
TagFloat (const float value = 0);
const float value () const;
protected:
virtual void readPayloadFromData (QDataStream &data) override;
virtual void writePayloadToData (QDataStream &data) const override;
private:
float m_value;
};
#endif //NBTMODIFIER_TAGFLOAT_H

@ -1,18 +0,0 @@
#include "TagInt.h"
#include <QtEndian>
#include <QtCore/QDataStream>
TagInt::TagInt (const qint32 value) : AbstractNamedTag(ID), m_value(value) {}
const qint32 TagInt::value () const {
return m_value;
}
void TagInt::readPayloadFromData (QDataStream &data) {
data >> m_value;
m_value = qFromBigEndian(m_value);
}
void TagInt::writePayloadToData (QDataStream &data) const {
data << qToBigEndian(m_value);
}

@ -1,22 +0,0 @@
#ifndef NBTMODIFIER_TAGINT_H
#define NBTMODIFIER_TAGINT_H
#include "AbstractNamedTag.h"
class TagInt : public AbstractNamedTag {
public:
static constexpr quint8 ID = 3;
TagInt (const qint32 value = 0);
const qint32 value () const;
protected:
virtual void readPayloadFromData (QDataStream &data) override;
virtual void writePayloadToData (QDataStream &data) const override;
private:
qint32 m_value;
};
#endif //NBTMODIFIER_TAGINT_H

@ -1,18 +0,0 @@
#include "TagLong.h"
#include <QtEndian>
#include <QtCore/QDataStream>
TagLong::TagLong (const qint64 value) : AbstractNamedTag(ID), m_value(value) {}
const qint64 TagLong::value () const {
return m_value;
}
void TagLong::readPayloadFromData (QDataStream &data) {
data >> m_value;
m_value = qFromBigEndian(m_value);
}
void TagLong::writePayloadToData (QDataStream &data) const {
data << qToBigEndian(m_value);
}

@ -1,22 +0,0 @@
#ifndef NBTMODIFIER_TAGLONG_H
#define NBTMODIFIER_TAGLONG_H
#include "AbstractNamedTag.h"
class TagLong : public AbstractNamedTag {
public:
static constexpr quint8 ID = 4;
TagLong (const qint64 value = 0);
const qint64 value () const;
protected:
virtual void readPayloadFromData (QDataStream &data) override;
virtual void writePayloadToData (QDataStream &data) const override;
private:
qint64 m_value;
};
#endif //NBTMODIFIER_TAGLONG_H

@ -1,18 +0,0 @@
#include "TagShort.h"
#include <QtEndian>
#include <QtCore/QDataStream>
TagShort::TagShort (const qint16 value) : AbstractNamedTag(ID), m_value(value) {}
const qint16 TagShort::value () const {
return m_value;
}
void TagShort::readPayloadFromData (QDataStream &data) {
data >> m_value;
m_value = qFromBigEndian(m_value);
}
void TagShort::writePayloadToData (QDataStream &data) const {
data << qToBigEndian(m_value);
}

@ -1,22 +0,0 @@
#ifndef NBTMODIFIER_TAGSHORT_H
#define NBTMODIFIER_TAGSHORT_H
#include "AbstractNamedTag.h"
class TagShort : public AbstractNamedTag {
public:
static constexpr quint8 ID = 2;
TagShort (const qint16 value = 0);
const qint16 value () const;
protected:
virtual void readPayloadFromData (QDataStream &data) override;
virtual void writePayloadToData (QDataStream &data) const override;
private:
qint16 m_value;
};
#endif //NBTMODIFIER_TAGSHORT_H

@ -20,9 +20,6 @@ public:
*/
void setName (const QString &name);
protected:
explicit AbstractNamedTag (const quint8 id);
virtual void readFromData (QDataStream &data) override;
virtual void writeToData (QDataStream &data) const override;
@ -43,6 +40,9 @@ protected:
*/
virtual void writePayloadToData (QDataStream &data) const = 0;
protected:
explicit AbstractNamedTag (const quint8 id);
private:
/**
* The tag name

@ -0,0 +1,78 @@
#include "AbstractTag.h"
//#include "TagEnd.h"
//#include "TagByte.h"
//#include "TagShort.h"
//#include "TagInt.h"
//#include "TagLong.h"
//#include "TagFloat.h"
//#include "TagDouble.h"
//#include "TagByteArray.h"
//#include "TagString.h"
//
//#include <QtCore/QDataStream>
//
//AbstractTag::AbstractTag (const quint8 id) : m_id(id) {}
//
//const quint8 AbstractTag::id () const {
// return m_id;
//}
//
//const quint8 AbstractTag::extractId (const QByteArray &data) {
// QDataStream stream(data);
//
// quint8 id;
// stream >> id;
//
// return id;
//}
//AbstractTag *AbstractTag::createEmptyFromId (const quint8 id) {
// switch (id) {
// case TagEnd::ID:
// return new TagEnd();
//
// case TagByte::ID:
// return new TagByte();
//
// case TagShort::ID:
// return new TagShort();
//
// case TagInt::ID:
// return new TagInt();
//
// case TagLong::ID:
// return new TagLong();
//
// case TagFloat::ID:
// return new TagFloat();
//
// case TagDouble::ID:
// return new TagDouble();
//
// case TagByteArray::ID:
// return new TagByteArray();
//
// case TagString::ID:
// return new TagString();
// }
//
// return nullptr;
//}
//AbstractTag *AbstractTag::createEmptyFromData (const QByteArray &data) {
// return createEmptyFromId(extractId(data));
//}
//
//QDataStream &operator << (QDataStream &data, const AbstractTag &tag) {
// data << tag.id();
// tag.writeToData(data);
//
// return data;
//}
//QDataStream &operator >> (QDataStream &data, AbstractTag &tag) {
// quint8 id;
// data >> id;
//
// tag.readFromData(data);
//
// return data;
//}

@ -0,0 +1,105 @@
#ifndef NBTMODIFIER_ABSTRACTTAG_H
#define NBTMODIFIER_ABSTRACTTAG_H
#include <QtGlobal>
class QDataStream;
/**
* Interface for all NBT tags
*/
class AbstractTag {
public:
/**
* When tag is destruct
*/
virtual inline ~AbstractTag () {};
/**
* The tag's id
*
* @return The tag's id
*/
const quint8 id () const;
/**
* Extract next tag's id from data (not consuming)
*
* @param data The data to read
*
* @return The next tag's id
*/
static const quint8 extractId (const QByteArray &data);
/**
* Create an empty tag of a giving id
*
* @param id The new tag's id
*
* @return The new tag, or nullptr if no valid id provided
*/
static AbstractTag *createEmptyFromId (const quint8 id);
/**
* Create an empty tag of the next tag's id from data (not consuming)
*
* @param data The data to read
*
* @return The new tag, or nullptr if invalid data provided
*/
static AbstractTag *createEmptyFromData (const QByteArray &data);
/**
* Read a tag from a data stream
*
* @param data The data stream
*
* @return True if read is success, otherwise false
*/
virtual void readFromData (QDataStream &data) = 0;
/**
* Write a tag to a data stream
*
* @param data The data stream
*
* @return True if write is success, otherwise false
*/
virtual void writeToData (QDataStream &data) const = 0;
/**
* Convenient operator to read a tag from a data stream
*
* @param tag The tag read
* @param data The data stream
*
* @return The data stream (allow call chaining)
*
* @see readFromData
*/
friend QDataStream &operator >> (QDataStream &data, AbstractTag &tag);
/**
* Convenient operator to write a tag to a data stream
*
* @param data The data stream
* @param tag The tag to write
*
* @return The data stream (allow call chaining)
*
* @see writeToData
*/
friend QDataStream &operator << (QDataStream &data, const AbstractTag &tag);
protected:
/**
* Create a new tag
*
* @param id
*/
explicit AbstractTag (const quint8 id);
private:
/**
* The tag's ID
*/
const quint8 m_id;
};
#endif //NBTMODIFIER_ABSTRACTTAG_H

@ -17,7 +17,7 @@ void TagByteArray::readPayloadFromData (QDataStream &data) {
m_value.clear();
for (qint32 elem = 0; elem < size.value(); elem++) {
TagByte tag;
data >> tag;
tag.readPayloadFromData(data);
m_value << tag;
}

@ -0,0 +1,45 @@
#include "TagList.h"
#include "TagByte.h"
#include "TagInt.h"
#include <QtCore/QDataStream>
TagList::TagList (quint8 elementsId, const QList<AbstractTag> value) : AbstractNamedTag(ID) {
m_elementsId = elementsId;
m_value.clear();
foreach(const AbstractTag &tag, value) {
if(tag.id() == m_elementsId) {
m_value.append(tag);
}
}
}
const quint8 TagList::elementsId() const {
return m_element;
}
const QList<AbstractTag> &TagList::value () const {
return m_value;
}
void TagList::readPayloadFromData (QDataStream &data) {
TagInt size;
data >> size;
m_value.clear();
for (qint32 elem = 0; elem < size.value(); elem++) {
TagByte tag;
data >> tag;
m_value << tag;
}
}
void TagList::writePayloadToData (QDataStream &data) const {
TagInt size(m_value.size());
data << size;
foreach(const AbstractTag &tag, m_value) {
data << tag;
}
}

@ -0,0 +1,26 @@
#ifndef NBTMODIFIER_TAGLIST_H
#define NBTMODIFIER_TAGLIST_H
#include "AbstractNamedTag.h"
#include <QtCore/QList>
class TagList : public AbstractNamedTag {
public:
static constexpr quint8 ID = 9;
TagList (quint8 elementsId = 0, const QList<AbstractTag> value = QList<AbstractTag>());
const quint8 elementsId () const;
const QList<AbstractTag> &value () const;
protected:
virtual void readPayloadFromData (QDataStream &data) override;
virtual void writePayloadToData (QDataStream &data) const override;
private:
quint8 m_elementsId;
QList<AbstractTag> m_value;
};
#endif //NBTMODIFIER_TAGLIST_H
Loading…
Cancel
Save