DarkflameServer/dCommon/GeneralUtils.h
jadebenn 6de224a2fa
chore: miscellaneous code, formatting, and syntax cleanup (#1351)
* miscellaneous code, formatting, and syntax cleanup

* update

* update again

* updated to account for feedback
2023-12-23 18:11:00 -06:00

264 lines
6.9 KiB
C++

#pragma once
// C++
#include <stdint.h>
#include <random>
#include <time.h>
#include <string>
#include <type_traits>
#include <functional>
#include <type_traits>
#include <stdexcept>
#include <BitStream.h>
#include "NiPoint3.h"
#include "Game.h"
#include "Logger.h"
enum eInventoryType : uint32_t;
enum class eObjectBits : size_t;
enum class eReplicaComponentType : uint32_t;
/*!
\file GeneralUtils.hpp
\brief A namespace containing general utility functions
*/
//! The general utils namespace
namespace GeneralUtils {
//! Converts a plain ASCII string to a UTF-16 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
//! Converts a UTF-8 String to a UTF-16 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-16 representation of the string
*/
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
//! Internal, do not use
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
//! Converts a UTF-16 string to a UTF-8 string
/*!
\param string The string to convert
\param size A size to trim the string to. Default is -1 (No trimming)
\return An UTF-8 representation of the string
*/
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
/**
* Compares two basic strings but does so ignoring case sensitivity
* \param a the first string to compare against the second string
* \param b the second string to compare against the first string
* @return if the two strings are equal
*/
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
// MARK: Bits
// MARK: Bits
//! Sets a bit on a numerical value
template <typename T>
inline void SetBit(T& value, eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8) - 1) {
return;
}
value |= static_cast<T>(1) << index;
}
//! Clears a bit on a numerical value
template <typename T>
inline void ClearBit(T& value, eObjectBits bits) {
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
auto index = static_cast<size_t>(bits);
if (index > (sizeof(T) * 8 - 1)) {
return;
}
value &= ~(static_cast<T>(1) << index);
}
//! Sets a specific bit in a signed 64-bit integer
/*!
\param value The value to set the bit for
\param index The index of the bit
*/
int64_t SetBit(int64_t value, uint32_t index);
//! Clears a specific bit in a signed 64-bit integer
/*!
\param value The value to clear the bit from
\param index The index of the bit
*/
int64_t ClearBit(int64_t value, uint32_t index);
//! Checks a specific bit in a signed 64-bit integer
/*!
\parma value The value to check the bit in
\param index The index of the bit
\return Whether or not the bit is set
*/
bool CheckBit(int64_t value, uint32_t index);
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
std::u16string ReadWString(RakNet::BitStream* inStream);
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
std::vector<std::u16string> SplitString(const std::u16string& str, char16_t delimiter);
std::vector<std::string> SplitString(const std::string& str, char delimiter);
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
template <typename T>
T Parse(const char* value);
template <>
inline bool Parse(const char* value) {
return std::stoi(value);
}
template <>
inline int32_t Parse(const char* value) {
return std::stoi(value);
}
template <>
inline int64_t Parse(const char* value) {
return std::stoll(value);
}
template <>
inline float Parse(const char* value) {
return std::stof(value);
}
template <>
inline double Parse(const char* value) {
return std::stod(value);
}
template <>
inline uint16_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint32_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint64_t Parse(const char* value) {
return std::stoull(value);
}
template <>
inline eInventoryType Parse(const char* value) {
return static_cast<eInventoryType>(std::stoul(value));
}
template <>
inline eReplicaComponentType Parse(const char* value) {
return static_cast<eReplicaComponentType>(std::stoul(value));
}
template <typename T>
bool TryParse(const char* value, T& dst) {
try {
dst = Parse<T>(value);
return true;
} catch (...) {
return false;
}
}
template <typename T>
T Parse(const std::string& value) {
return Parse<T>(value.c_str());
}
template <typename T>
bool TryParse(const std::string& value, T& dst) {
return TryParse<T>(value.c_str(), dst);
}
bool TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst);
template<typename T>
std::u16string to_u16string(T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
}
// From boost::hash_combine
template <class T>
void hash_combine(std::size_t& s, const T& v) {
std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
}
// MARK: Random Number Generation
//! Generates a random number
/*!
\param min The minimum the generate from
\param max The maximum to generate to
*/
template <typename T>
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
std::uniform_int_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
} else if (std::is_floating_point_v<T>) {
std::uniform_real_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
}
return T();
}
/**
* Casts the value of an enum entry to its underlying type
* @param entry Enum entry to cast
* @returns The enum entry's value in its underlying type
*/
template <typename eType>
inline constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) {
static_assert(std::is_enum_v<eType>, "Not an enum");
return static_cast<typename std::underlying_type_t<eType>>(entry);
}
// on Windows we need to undef these or else they conflict with our numeric limits calls
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
#ifdef _WIN32
#undef min
#undef max
#endif
template <typename T>
inline T GenerateRandomNumber() {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
}
}