mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-25 15:07:28 +00:00
e8590a5853
* Add tests and cleanup LDF header Also implements a speedup by using overloaded operators to put numbers directly to a stream as opposed to doing to_string first. Stage 2 of re-write Reduce scoping Add further optimizations Fix more edge cases Split out tests to many smaller ones Use EXPECT_NO_THROW Add edge cases to test Added these first with the before to confirm they failed, and now will be adding the remaining fixes needed to make the tests pass. Add edge case testing for LDF strings Add further tests Use characters instead of char* Update AMFDeserializeTests.cpp Add null tests * Add Test Fixture for dCommon * Add speed test * Convert to using string_view * Add explanation on early return * Remove "testing" code
224 lines
6.8 KiB
C++
224 lines
6.8 KiB
C++
#ifndef __LDFFORMAT__H__
|
|
#define __LDFFORMAT__H__
|
|
|
|
// Custom Classes
|
|
#include "dCommonVars.h"
|
|
#include "GeneralUtils.h"
|
|
|
|
// C++
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <sstream>
|
|
|
|
// RakNet
|
|
#include "BitStream.h"
|
|
|
|
enum eLDFType {
|
|
LDF_TYPE_UNKNOWN = -1, //!< Unknown data type
|
|
LDF_TYPE_UTF_16 = 0, //!< UTF-16 wstring data type
|
|
LDF_TYPE_S32 = 1, //!< Signed 32-bit data type
|
|
LDF_TYPE_FLOAT = 3, //!< Float data type
|
|
LDF_TYPE_DOUBLE = 4, //!< Double data type
|
|
LDF_TYPE_U32 = 5, //!< Unsigned 32-bit data type
|
|
LDF_TYPE_BOOLEAN = 7, //!< Boolean data type
|
|
LDF_TYPE_U64 = 8, //!< Unsigned 64-bit data type (originally signed, templates won't work with both S64 & OBJID
|
|
LDF_TYPE_OBJID = 9, //!< Signed 64-bit data type (reserved for object IDs)
|
|
LDF_TYPE_UTF_8 = 13, //!< UTF-8 string data type
|
|
};
|
|
|
|
class LDFBaseData {
|
|
public:
|
|
|
|
virtual ~LDFBaseData() {}
|
|
|
|
virtual void WriteToPacket(RakNet::BitStream* packet) = 0;
|
|
|
|
virtual const std::u16string& GetKey() = 0;
|
|
|
|
virtual eLDFType GetValueType() = 0;
|
|
|
|
/** Gets a string from the key/value pair
|
|
* @param includeKey Whether or not to include the key in the data
|
|
* @param includeTypeId Whether or not to include the type id in the data
|
|
* @return The string representation of the data
|
|
*/
|
|
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0;
|
|
|
|
virtual std::string GetValueAsString() = 0;
|
|
|
|
virtual LDFBaseData* Copy() = 0;
|
|
|
|
/**
|
|
* Given an input string, return the data as a LDF key.
|
|
*/
|
|
static LDFBaseData* DataFromString(const std::string_view& format);
|
|
|
|
};
|
|
|
|
template<typename T>
|
|
class LDFData: public LDFBaseData {
|
|
private:
|
|
std::u16string key;
|
|
T value;
|
|
|
|
//! Writes the key to the packet
|
|
void WriteKey(RakNet::BitStream* packet) {
|
|
packet->Write(static_cast<uint8_t>(this->key.length() * sizeof(uint16_t)));
|
|
for (uint32_t i = 0; i < this->key.length(); ++i) {
|
|
packet->Write(static_cast<uint16_t>(this->key[i]));
|
|
}
|
|
}
|
|
|
|
//! Writes the value to the packet
|
|
void WriteValue(RakNet::BitStream* packet) {
|
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
|
packet->Write(this->value);
|
|
}
|
|
|
|
public:
|
|
|
|
//! Initializer
|
|
LDFData(const std::u16string& key, const T& value) {
|
|
this->key = key;
|
|
this->value = value;
|
|
}
|
|
|
|
//! Destructor
|
|
~LDFData(void) override {}
|
|
|
|
//! Gets the value
|
|
/*!
|
|
\return The value
|
|
*/
|
|
const T& GetValue(void) { return this->value; }
|
|
|
|
//! Sets the value
|
|
/*!
|
|
\param value The value to set to
|
|
*/
|
|
void SetValue(T value) { this->value = value; };
|
|
|
|
//! Gets the value string
|
|
/*!
|
|
\return The value string
|
|
*/
|
|
std::string GetValueString(void) { return ""; }
|
|
|
|
//! Writes the data to a packet
|
|
/*!
|
|
\param packet The packet
|
|
*/
|
|
void WriteToPacket(RakNet::BitStream* packet) override {
|
|
this->WriteKey(packet);
|
|
this->WriteValue(packet);
|
|
}
|
|
|
|
//! Gets the key
|
|
/*!
|
|
\return The key
|
|
*/
|
|
const std::u16string& GetKey(void) override { return this->key; }
|
|
|
|
//! Gets the LDF Type
|
|
/*!
|
|
\return The LDF value type
|
|
*/
|
|
eLDFType GetValueType(void) override { return LDF_TYPE_UNKNOWN; }
|
|
|
|
//! Gets the string data
|
|
/*!
|
|
\param includeKey Whether or not to include the key in the data
|
|
\param includeTypeId Whether or not to include the type id in the data
|
|
\return The string representation of the data
|
|
*/
|
|
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) override {
|
|
if (GetValueType() == -1) {
|
|
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
|
|
}
|
|
|
|
std::stringstream stream;
|
|
|
|
if (includeKey) {
|
|
const std::string& sKey = GeneralUtils::UTF16ToWTF8(this->key, this->key.size());
|
|
stream << sKey << '=';
|
|
}
|
|
|
|
if (includeTypeId) {
|
|
stream << this->GetValueType() << ':';
|
|
}
|
|
|
|
const std::string& sData = this->GetValueString();
|
|
|
|
stream << sData;
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
std::string GetValueAsString() override {
|
|
return this->GetValueString();
|
|
}
|
|
|
|
LDFBaseData* Copy() override {
|
|
return new LDFData<T>(key, value);
|
|
}
|
|
|
|
inline static T Default = {};
|
|
};
|
|
|
|
// LDF Types
|
|
template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) { return LDF_TYPE_UTF_16; };
|
|
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) { return LDF_TYPE_S32; };
|
|
template<> inline eLDFType LDFData<float>::GetValueType(void) { return LDF_TYPE_FLOAT; };
|
|
template<> inline eLDFType LDFData<double>::GetValueType(void) { return LDF_TYPE_DOUBLE; };
|
|
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) { return LDF_TYPE_U32; };
|
|
template<> inline eLDFType LDFData<bool>::GetValueType(void) { return LDF_TYPE_BOOLEAN; };
|
|
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) { return LDF_TYPE_U64; };
|
|
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) { return LDF_TYPE_OBJID; };
|
|
template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF_TYPE_UTF_8; };
|
|
|
|
// The specialized version for std::u16string (UTF-16)
|
|
template<>
|
|
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream* packet) {
|
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
|
|
|
packet->Write(static_cast<uint32_t>(this->value.length()));
|
|
for (uint32_t i = 0; i < this->value.length(); ++i) {
|
|
packet->Write(static_cast<uint16_t>(this->value[i]));
|
|
}
|
|
}
|
|
|
|
// The specialized version for bool
|
|
template<>
|
|
inline void LDFData<bool>::WriteValue(RakNet::BitStream* packet) {
|
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
|
|
|
packet->Write(static_cast<uint8_t>(this->value));
|
|
}
|
|
|
|
// The specialized version for std::string (UTF-8)
|
|
template<>
|
|
inline void LDFData<std::string>::WriteValue(RakNet::BitStream* packet) {
|
|
packet->Write(static_cast<uint8_t>(this->GetValueType()));
|
|
|
|
packet->Write(static_cast<uint32_t>(this->value.length()));
|
|
for (uint32_t i = 0; i < this->value.length(); ++i) {
|
|
packet->Write(static_cast<uint8_t>(this->value[i]));
|
|
}
|
|
}
|
|
|
|
template<> inline std::string LDFData<std::u16string>::GetValueString() {
|
|
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
|
}
|
|
|
|
template<> inline std::string LDFData<int32_t>::GetValueString() { return std::to_string(this->value); }
|
|
template<> inline std::string LDFData<float>::GetValueString() { return std::to_string(this->value); }
|
|
template<> inline std::string LDFData<double>::GetValueString() { return std::to_string(this->value); }
|
|
template<> inline std::string LDFData<uint32_t>::GetValueString() { return std::to_string(this->value); }
|
|
template<> inline std::string LDFData<bool>::GetValueString() { return std::to_string(this->value); }
|
|
template<> inline std::string LDFData<uint64_t>::GetValueString() { return std::to_string(this->value); }
|
|
template<> inline std::string LDFData<LWOOBJID>::GetValueString() { return std::to_string(this->value); }
|
|
|
|
template<> inline std::string LDFData<std::string>::GetValueString() { return this->value; }
|
|
|
|
#endif //!__LDFFORMAT__H__
|