mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-17 04:04:21 +00:00
chore: cleanup pointer management for LDF data (#1995)
* change network settings from vector to LwoNameValue * move settings on Entity to managed memory * Migrate more members * chore: remove pointer leakage from raw ldf pointers * feedback * fix ci
This commit is contained in:
@@ -49,11 +49,10 @@ if (UNIX)
|
||||
elseif (WIN32)
|
||||
include(FetchContent)
|
||||
|
||||
# TODO Keep an eye on the zlib repository for an update to disable testing. Don't forget to update CMakePresets
|
||||
FetchContent_Declare(
|
||||
zlib
|
||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
||||
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.3.2.zip
|
||||
URL_HASH MD5=adbba6eef8960c3412818b2e241f46dc
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
@@ -62,12 +61,12 @@ elseif (WIN32)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
||||
# Disable warning about the minimum version of cmake used for bcrypt being deprecated in the future
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
|
||||
# Disable zlib tests
|
||||
set(ZLIB_BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
||||
|
||||
FetchContent_MakeAvailable(zlib)
|
||||
|
||||
set(ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
|
||||
set_target_properties(zlib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}")
|
||||
add_library(ZLIB::ZLIB ALIAS zlib)
|
||||
else ()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
|
||||
@@ -10,163 +10,151 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using LDFKey = std::string_view;
|
||||
using LDFTypeAndValue = std::string_view;
|
||||
|
||||
using LDFType = std::string_view;
|
||||
using LDFValue = std::string_view;
|
||||
|
||||
//! Returns a pointer to a LDFData value based on string format
|
||||
LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
||||
std::unique_ptr<LDFBaseData> LDFBaseData::DataFromString(const std::string_view& format) {
|
||||
std::unique_ptr<LDFBaseData> toReturn;
|
||||
// A valid LDF must be at least 3 characters long (=0:) is the shortest valid LDF (empty UTF-16 key with no initial value)
|
||||
if (format.empty() || format.length() <= 2) return nullptr;
|
||||
auto equalsPosition = format.find('=');
|
||||
// You can have an empty key, just make sure the type and value might exist
|
||||
if (equalsPosition == std::string::npos || equalsPosition == (format.size() - 1)) return nullptr;
|
||||
if (!format.empty() && format.length() > 2) {
|
||||
auto equalsPosition = format.find('=');
|
||||
// You can have an empty key, just make sure the type and value might exist
|
||||
if (equalsPosition != std::string::npos && equalsPosition != (format.size() - 1)) {
|
||||
|
||||
std::pair<LDFKey, LDFTypeAndValue> keyValue;
|
||||
keyValue.first = format.substr(0, equalsPosition);
|
||||
keyValue.second = format.substr(equalsPosition + 1, format.size());
|
||||
const std::string_view keyValue = format.substr(0, equalsPosition);
|
||||
const std::string_view typeAndValue = format.substr(equalsPosition + 1, format.size());
|
||||
|
||||
std::u16string key = GeneralUtils::ASCIIToUTF16(keyValue.first);
|
||||
const auto key = GeneralUtils::ASCIIToUTF16(keyValue);
|
||||
|
||||
auto colonPosition = keyValue.second.find(':');
|
||||
const auto colonPosition = typeAndValue.find(':');
|
||||
|
||||
// If : is the first thing after an =, then this is an invalid LDF since
|
||||
// we dont have a type to use.
|
||||
if (colonPosition == std::string::npos || colonPosition == 0) return nullptr;
|
||||
// If : is the first thing after an =, then this is an invalid LDF since
|
||||
// we dont have a type to use.
|
||||
if (colonPosition != std::string::npos && colonPosition != 0) {
|
||||
const std::string_view ldfType = typeAndValue.substr(0, colonPosition);
|
||||
const std::string_view ldfValue = typeAndValue.substr(colonPosition + 1, typeAndValue.size());
|
||||
|
||||
std::pair<LDFType, LDFValue> ldfTypeAndValue;
|
||||
ldfTypeAndValue.first = keyValue.second.substr(0, colonPosition);
|
||||
ldfTypeAndValue.second = keyValue.second.substr(colonPosition + 1, keyValue.second.size());
|
||||
// Only allow empty values for string values.
|
||||
if (!ldfValue.empty() || (ldfType == "0" /* UTF-16 */ || ldfType == "13" /* UTF-8 */)) {
|
||||
const eLDFType type = GeneralUtils::TryParse<eLDFType>(ldfType, LDF_TYPE_UNKNOWN);
|
||||
switch (type) {
|
||||
case LDF_TYPE_UTF_16: {
|
||||
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfValue);
|
||||
toReturn.reset(new LDFData<std::u16string>(key, data));
|
||||
break;
|
||||
}
|
||||
|
||||
// Only allow empty values for string values.
|
||||
if (ldfTypeAndValue.second.size() == 0 && !(ldfTypeAndValue.first == "0" || ldfTypeAndValue.first == "13")) return nullptr;
|
||||
case LDF_TYPE_S32: {
|
||||
const auto data = GeneralUtils::TryParse<int32_t>(ldfValue);
|
||||
if (data) {
|
||||
toReturn.reset(new LDFData<int32_t>(key, data.value()));
|
||||
} else {
|
||||
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
}
|
||||
|
||||
eLDFType type;
|
||||
char* storage;
|
||||
try {
|
||||
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
|
||||
} catch (std::exception) {
|
||||
LOG("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LDFBaseData* returnValue = nullptr;
|
||||
switch (type) {
|
||||
case LDF_TYPE_UTF_16: {
|
||||
std::u16string data = GeneralUtils::UTF8ToUTF16(ldfTypeAndValue.second);
|
||||
returnValue = new LDFData<std::u16string>(key, data);
|
||||
break;
|
||||
}
|
||||
case LDF_TYPE_FLOAT: {
|
||||
const auto data = GeneralUtils::TryParse<float>(ldfValue);
|
||||
if (data) {
|
||||
toReturn.reset(new LDFData<float>(key, data.value()));
|
||||
} else {
|
||||
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_S32: {
|
||||
const auto data = GeneralUtils::TryParse<int32_t>(ldfTypeAndValue.second);
|
||||
if (!data) {
|
||||
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
return nullptr;
|
||||
}
|
||||
returnValue = new LDFData<int32_t>(key, data.value());
|
||||
case LDF_TYPE_DOUBLE: {
|
||||
const auto data = GeneralUtils::TryParse<double>(ldfValue);
|
||||
if (data) {
|
||||
toReturn.reset(new LDFData<double>(key, data.value()));
|
||||
} else {
|
||||
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case LDF_TYPE_U32:
|
||||
{
|
||||
uint32_t data;
|
||||
bool parsed = true;
|
||||
// Have to do this really weird parsing to allow for copy ellision
|
||||
if (ldfValue == "true") {
|
||||
data = 1;
|
||||
} else if (ldfValue == "false") {
|
||||
data = 0;
|
||||
} else {
|
||||
const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfValue);
|
||||
if (!dataOptional) {
|
||||
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
parsed = false;
|
||||
} else {
|
||||
data = dataOptional.value();
|
||||
}
|
||||
}
|
||||
|
||||
case LDF_TYPE_FLOAT: {
|
||||
const auto data = GeneralUtils::TryParse<float>(ldfTypeAndValue.second);
|
||||
if (!data) {
|
||||
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
return nullptr;
|
||||
}
|
||||
returnValue = new LDFData<float>(key, data.value());
|
||||
break;
|
||||
}
|
||||
if (parsed) toReturn.reset(new LDFData<uint32_t>(key, data));
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_DOUBLE: {
|
||||
const auto data = GeneralUtils::TryParse<double>(ldfTypeAndValue.second);
|
||||
if (!data) {
|
||||
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
return nullptr;
|
||||
}
|
||||
returnValue = new LDFData<double>(key, data.value());
|
||||
break;
|
||||
}
|
||||
case LDF_TYPE_BOOLEAN: {
|
||||
bool data;
|
||||
bool parsed = true;
|
||||
// Have to do this really weird parsing to allow for copy ellision
|
||||
if (ldfValue == "true") {
|
||||
data = true;
|
||||
} else if (ldfValue == "false") {
|
||||
data = false;
|
||||
} else {
|
||||
const auto dataOptional = GeneralUtils::TryParse<bool>(ldfValue);
|
||||
if (!dataOptional) {
|
||||
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
parsed = false;
|
||||
} else {
|
||||
data = dataOptional.value();
|
||||
}
|
||||
}
|
||||
|
||||
case LDF_TYPE_U32:
|
||||
{
|
||||
uint32_t data;
|
||||
if (parsed) toReturn.reset(new LDFData<bool>(key, data));
|
||||
break;
|
||||
}
|
||||
|
||||
if (ldfTypeAndValue.second == "true") {
|
||||
data = 1;
|
||||
} else if (ldfTypeAndValue.second == "false") {
|
||||
data = 0;
|
||||
} else {
|
||||
const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfTypeAndValue.second);
|
||||
if (!dataOptional) {
|
||||
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
return nullptr;
|
||||
case LDF_TYPE_U64: {
|
||||
const auto data = GeneralUtils::TryParse<uint64_t>(ldfValue);
|
||||
if (data) {
|
||||
toReturn.reset(new LDFData<uint64_t>(key, data.value()));
|
||||
} else {
|
||||
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_OBJID: {
|
||||
const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfValue);
|
||||
if (data) {
|
||||
toReturn.reset(new LDFData<LWOOBJID>(key, data.value()));
|
||||
} else {
|
||||
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_UTF_8: {
|
||||
toReturn.reset(new LDFData<std::string>(key, ldfValue.data()));
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_UNKNOWN:
|
||||
[[fallthrough]];
|
||||
default: {
|
||||
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfValue.data(), format.data());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
data = dataOptional.value();
|
||||
}
|
||||
|
||||
returnValue = new LDFData<uint32_t>(key, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_BOOLEAN: {
|
||||
bool data;
|
||||
|
||||
if (ldfTypeAndValue.second == "true") {
|
||||
data = true;
|
||||
} else if (ldfTypeAndValue.second == "false") {
|
||||
data = false;
|
||||
} else {
|
||||
const auto dataOptional = GeneralUtils::TryParse<bool>(ldfTypeAndValue.second);
|
||||
if (!dataOptional) {
|
||||
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
return nullptr;
|
||||
}
|
||||
data = dataOptional.value();
|
||||
}
|
||||
|
||||
returnValue = new LDFData<bool>(key, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_U64: {
|
||||
const auto data = GeneralUtils::TryParse<uint64_t>(ldfTypeAndValue.second);
|
||||
if (!data) {
|
||||
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
return nullptr;
|
||||
}
|
||||
returnValue = new LDFData<uint64_t>(key, data.value());
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_OBJID: {
|
||||
const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfTypeAndValue.second);
|
||||
if (!data) {
|
||||
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
return nullptr;
|
||||
}
|
||||
returnValue = new LDFData<LWOOBJID>(key, data.value());
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_UTF_8: {
|
||||
std::string data = ldfTypeAndValue.second.data();
|
||||
returnValue = new LDFData<std::string>(key, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case LDF_TYPE_UNKNOWN: {
|
||||
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#ifndef __LDFFORMAT__H__
|
||||
#define __LDFFORMAT__H__
|
||||
#ifndef LDFFORMAT_H
|
||||
#define LDFFORMAT_H
|
||||
|
||||
// Custom Classes
|
||||
#include "dCommonVars.h"
|
||||
#include "GeneralUtils.h"
|
||||
|
||||
// C++
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
@@ -46,17 +47,17 @@ public:
|
||||
|
||||
virtual std::string GetValueAsString() const = 0;
|
||||
|
||||
virtual LDFBaseData* Copy() const = 0;
|
||||
virtual std::unique_ptr<LDFBaseData> Copy() const = 0;
|
||||
|
||||
/**
|
||||
* Given an input string, return the data as a LDF key.
|
||||
*/
|
||||
static LDFBaseData* DataFromString(const std::string_view& format);
|
||||
static std::unique_ptr<LDFBaseData> DataFromString(const std::string_view& format);
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class LDFData: public LDFBaseData {
|
||||
class LDFData : public LDFBaseData {
|
||||
private:
|
||||
std::u16string key;
|
||||
T value;
|
||||
@@ -164,8 +165,8 @@ public:
|
||||
return this->GetValueString();
|
||||
}
|
||||
|
||||
LDFBaseData* Copy() const override {
|
||||
return new LDFData<T>(key, value);
|
||||
std::unique_ptr<LDFBaseData> Copy() const override {
|
||||
return std::make_unique<LDFData<T>>(key, value);
|
||||
}
|
||||
|
||||
inline static const T Default = {};
|
||||
@@ -226,4 +227,81 @@ template<> inline std::string LDFData<LWOOBJID>::GetValueString() const { return
|
||||
|
||||
template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
|
||||
|
||||
#endif //!__LDFFORMAT__H__
|
||||
struct LwoNameValue {
|
||||
using LDFPtr = std::unique_ptr<LDFBaseData>;
|
||||
using ValueType = std::map<std::u16string, LDFPtr>;
|
||||
|
||||
LwoNameValue& operator=(const LwoNameValue& other) {
|
||||
this->values = other.Copy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Insert(const std::u16string& key, const T& value) {
|
||||
this->values.insert_or_assign(key, std::unique_ptr(std::make_unique<LDFData<T>>(key, value)));
|
||||
}
|
||||
|
||||
void Insert(const std::u16string& key, const char* value) {
|
||||
this->Insert<std::string>(key, value);
|
||||
}
|
||||
|
||||
void Insert(const std::u16string& key, const char16_t* value) {
|
||||
this->Insert<std::u16string>(key, value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Insert(const std::string& key, const T& value) {
|
||||
this->Insert<T>(GeneralUtils::UTF8ToUTF16(key), value);
|
||||
}
|
||||
|
||||
void Insert(const std::string& key, const char* value) {
|
||||
this->Insert<std::string>(GeneralUtils::UTF8ToUTF16(key), value);
|
||||
}
|
||||
|
||||
void Insert(const std::string& key, const char16_t* value) {
|
||||
this->Insert<std::u16string>(GeneralUtils::UTF8ToUTF16(key), value);
|
||||
}
|
||||
|
||||
const LDFPtr& ParseInsert(const std::string& data) {
|
||||
LDFPtr toInsert(LDFBaseData::DataFromString(data));
|
||||
return toInsert ?
|
||||
this->values.insert_or_assign(toInsert->GetKey(), std::move(toInsert)).first->second :
|
||||
this->values.insert_or_assign(u"FAILED_TO_PARSE_" + GeneralUtils::UTF8ToUTF16(data), std::make_unique<LDFData<std::string>>("", "")).first->second;
|
||||
}
|
||||
|
||||
const LDFPtr& ParseInsert(const std::u16string& data) {
|
||||
return this->ParseInsert(GeneralUtils::UTF16ToWTF8(data));
|
||||
}
|
||||
|
||||
ValueType::const_iterator begin() const {
|
||||
return this->values.cbegin();
|
||||
}
|
||||
|
||||
ValueType::const_iterator end() const {
|
||||
return this->values.cend();
|
||||
}
|
||||
|
||||
void Erase(const std::u16string& key) {
|
||||
this->values.erase(key);
|
||||
}
|
||||
|
||||
void Erase(const std::string& key) {
|
||||
this->Erase(GeneralUtils::ASCIIToUTF16(key));
|
||||
}
|
||||
|
||||
LwoNameValue() = default;
|
||||
|
||||
LwoNameValue(const LwoNameValue& other) {
|
||||
this->values = other.Copy();
|
||||
}
|
||||
|
||||
ValueType values;
|
||||
private:
|
||||
ValueType Copy() const {
|
||||
ValueType copy;
|
||||
for (const auto& [key, value] : this->values) copy.insert_or_assign(key, value->Copy());
|
||||
return copy;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //!LDFFORMAT_H
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __NIPOINT3_H__
|
||||
#define __NIPOINT3_H__
|
||||
|
||||
#ifndef GLM_ENABLE_EXPERIMENTAL
|
||||
# define GLM_ENABLE_EXPERIMENTAL
|
||||
#endif
|
||||
/*!
|
||||
\file NiPoint3.hpp
|
||||
\brief Defines a point in space in XYZ coordinates
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef NIQUATERNION_H
|
||||
#define NIQUATERNION_H
|
||||
|
||||
#ifndef GLM_ENABLE_EXPERIMENTAL
|
||||
# define GLM_ENABLE_EXPERIMENTAL
|
||||
#endif
|
||||
// Custom Classes
|
||||
#include "NiPoint3.h"
|
||||
|
||||
|
||||
@@ -111,18 +111,6 @@ private:
|
||||
|
||||
constexpr LWOSCENEID LWOSCENEID_INVALID = -1;
|
||||
|
||||
struct LWONameValue {
|
||||
uint32_t length = 0; //!< The length of the name
|
||||
std::u16string name; //!< The name
|
||||
|
||||
LWONameValue() = default;
|
||||
|
||||
LWONameValue(const std::u16string& name) {
|
||||
this->name = name;
|
||||
this->length = static_cast<uint32_t>(name.length());
|
||||
}
|
||||
};
|
||||
|
||||
struct FriendData {
|
||||
public:
|
||||
bool isOnline = false;
|
||||
|
||||
Reference in New Issue
Block a user