From e73eed247e3eca8730b985f81dceb2b7b1f4a207 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 26 Mar 2025 19:08:31 +0100 Subject: [PATCH] Apply some refactoring/cleanup to mainly util functions --- src/client/client.cpp | 5 --- src/client/client.h | 7 +++- src/filesys.cpp | 54 +++++++++++++------------- src/filesys.h | 11 +++--- src/porting.cpp | 2 +- src/unittest/test_utilities.cpp | 10 +++++ src/util/container.h | 9 ++--- src/util/hashing.cpp | 2 + src/util/hex.h | 23 +++++------ src/util/numeric.cpp | 16 ++------ src/util/numeric.h | 69 +++++++++++++++++++++------------ src/util/pointer.h | 56 +++++++++++++++----------- src/util/serialize.h | 6 +-- src/util/sha1.cpp | 25 ++++-------- src/util/sha1.h | 9 ++--- src/util/srp.h | 2 + src/util/string.cpp | 28 ++++++------- src/util/string.h | 4 +- src/util/thread.h | 12 +++++- 19 files changed, 190 insertions(+), 160 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 031bed8d7..214420de5 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1642,11 +1642,6 @@ void Client::inventoryAction(InventoryAction *a) delete a; } -float Client::getAnimationTime() -{ - return m_animation_time; -} - int Client::getCrackLevel() { return m_crack_level; diff --git a/src/client/client.h b/src/client/client.h index 237dd93b6..e4cbac1f5 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -277,7 +277,10 @@ public: return m_env.getPlayerNames(); } - float getAnimationTime(); + float getAnimationTime() const + { + return m_animation_time; + } int getCrackLevel(); v3s16 getCrackPos(); @@ -294,7 +297,7 @@ public: bool getChatMessage(std::wstring &message); void typeChatMessage(const std::wstring& message); - u64 getMapSeed(){ return m_map_seed; } + u64 getMapSeed() const { return m_map_seed; } void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false); // Including blocks at appropriate edges diff --git a/src/filesys.cpp b/src/filesys.cpp index be1751c0b..62352403f 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -136,20 +136,23 @@ bool IsDir(const std::string &path) (attr & FILE_ATTRIBUTE_DIRECTORY)); } +bool IsFile(const std::string &path) +{ + DWORD attr = GetFileAttributes(path.c_str()); + return (attr != INVALID_FILE_ATTRIBUTES && + !(attr & FILE_ATTRIBUTE_DIRECTORY)); +} + bool IsExecutable(const std::string &path) { DWORD type; return GetBinaryType(path.c_str(), &type) != 0; } -bool IsDirDelimiter(char c) -{ - return c == '/' || c == '\\'; -} - bool RecursiveDelete(const std::string &path) { infostream << "Recursively deleting \"" << path << "\"" << std::endl; + assert(IsPathAbsolute(path)); if (!IsDir(path)) { infostream << "RecursiveDelete: Deleting file " << path << std::endl; if (!DeleteFile(path.c_str())) { @@ -181,19 +184,9 @@ bool RecursiveDelete(const std::string &path) bool DeleteSingleFileOrEmptyDirectory(const std::string &path) { - DWORD attr = GetFileAttributes(path.c_str()); - bool is_directory = (attr != INVALID_FILE_ATTRIBUTES && - (attr & FILE_ATTRIBUTE_DIRECTORY)); - if(!is_directory) - { - bool did = DeleteFile(path.c_str()); - return did; - } - else - { - bool did = RemoveDirectory(path.c_str()); - return did; - } + if (!IsDir(path)) + return DeleteFile(path.c_str()); + return RemoveDirectory(path.c_str()); } std::string TempPath() @@ -336,8 +329,7 @@ bool CreateDir(const std::string &path) bool PathExists(const std::string &path) { - struct stat st{}; - return (stat(path.c_str(),&st) == 0); + return access(path.c_str(), F_OK) == 0; } bool IsPathAbsolute(const std::string &path) @@ -348,21 +340,29 @@ bool IsPathAbsolute(const std::string &path) bool IsDir(const std::string &path) { struct stat statbuf{}; - if(stat(path.c_str(), &statbuf)) + if (stat(path.c_str(), &statbuf)) return false; // Actually error; but certainly not a directory return ((statbuf.st_mode & S_IFDIR) == S_IFDIR); } +bool IsFile(const std::string &path) +{ + struct stat statbuf{}; + if (stat(path.c_str(), &statbuf)) + return false; +#ifdef S_IFSOCK + // sockets cannot be opened in any way, so they are not files. + if ((statbuf.st_mode & S_IFSOCK) == S_IFSOCK) + return false; +#endif + return ((statbuf.st_mode & S_IFDIR) != S_IFDIR); +} + bool IsExecutable(const std::string &path) { return access(path.c_str(), X_OK) == 0; } -bool IsDirDelimiter(char c) -{ - return c == '/'; -} - bool RecursiveDelete(const std::string &path) { /* @@ -877,7 +877,7 @@ const char *GetFilenameFromPath(const char *path) { const char *filename = strrchr(path, DIR_DELIM_CHAR); // Consistent with IsDirDelimiter this function handles '/' too - if (DIR_DELIM_CHAR != '/') { + if constexpr (DIR_DELIM_CHAR != '/') { const char *tmp = strrchr(path, '/'); if (tmp && tmp > filename) filename = tmp; diff --git a/src/filesys.h b/src/filesys.h index 0e974d822..a2f7b749c 100644 --- a/src/filesys.h +++ b/src/filesys.h @@ -49,15 +49,14 @@ bool IsDir(const std::string &path); bool IsExecutable(const std::string &path); -inline bool IsFile(const std::string &path) +bool IsFile(const std::string &path); + +inline bool IsDirDelimiter(char c) { - return PathExists(path) && !IsDir(path); + return c == '/' || c == DIR_DELIM_CHAR; } -bool IsDirDelimiter(char c); - -// Only pass full paths to this one. True on success. -// NOTE: The WIN32 version returns always true. +// Only pass full paths to this one. returns true on success. bool RecursiveDelete(const std::string &path); bool DeleteSingleFileOrEmptyDirectory(const std::string &path); diff --git a/src/porting.cpp b/src/porting.cpp index faef75b7c..11ff63a88 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -270,7 +270,7 @@ const std::string &get_sysinfo() } -bool getCurrentWorkingDir(char *buf, size_t len) +[[maybe_unused]] static bool getCurrentWorkingDir(char *buf, size_t len) { #ifdef _WIN32 DWORD ret = GetCurrentDirectory(len, buf); diff --git a/src/unittest/test_utilities.cpp b/src/unittest/test_utilities.cpp index ac1f29b30..1a810c06d 100644 --- a/src/unittest/test_utilities.cpp +++ b/src/unittest/test_utilities.cpp @@ -47,6 +47,7 @@ public: void testIsBlockInSight(); void testColorizeURL(); void testSanitizeUntrusted(); + void testReadSeed(); }; static TestUtilities g_test_instance; @@ -82,6 +83,7 @@ void TestUtilities::runTests(IGameDef *gamedef) TEST(testIsBlockInSight); TEST(testColorizeURL); TEST(testSanitizeUntrusted); + TEST(testReadSeed); } //////////////////////////////////////////////////////////////////////////////// @@ -753,3 +755,11 @@ void TestUtilities::testSanitizeUntrusted() UASSERTEQ(auto, sanitize_untrusted("\x1b(", keep), "("); } } + +void TestUtilities::testReadSeed() +{ + UASSERTEQ(int, read_seed("123"), 123); + UASSERTEQ(int, read_seed("0x123"), 0x123); + // hashing should produce some non-zero number + UASSERT(read_seed("hello") != 0); +} diff --git a/src/util/container.h b/src/util/container.h index 19af68497..50a57fc08 100644 --- a/src/util/container.h +++ b/src/util/container.h @@ -362,11 +362,10 @@ public: // This conditional block was converted from a ternary to ensure no // temporary values are created in evaluating the return expression, // which could cause a dangling reference. - if (it != m_values.end()) { + if (it != m_values.end()) return it->second; - } else { + else return null_value; - } } void put(const K &key, const V &value) { @@ -430,7 +429,7 @@ public: return !!take(key); } - // Warning: not constant-time! + /// @warning not constant-time! size_t size() const { if (m_iterating) { // This is by no means impossible to determine, it's just annoying @@ -446,7 +445,7 @@ public: return n; } - // Warning: not constant-time! + /// @warning not constant-time! bool empty() const { if (m_iterating) return false; // maybe diff --git a/src/util/hashing.cpp b/src/util/hashing.cpp index 452cd6818..c1fed34f2 100644 --- a/src/util/hashing.cpp +++ b/src/util/hashing.cpp @@ -4,6 +4,8 @@ #include "hashing.h" +#define IN_HASHING_CPP + #include "debug.h" #include "config.h" #if USE_OPENSSL diff --git a/src/util/hex.h b/src/util/hex.h index 0d3ea6d0c..c528fe4bd 100644 --- a/src/util/hex.h +++ b/src/util/hex.h @@ -9,27 +9,22 @@ static const char hex_chars[] = "0123456789abcdef"; -static inline std::string hex_encode(const char *data, unsigned int data_size) +static inline std::string hex_encode(std::string_view data) { std::string ret; - ret.reserve(data_size * 2); - - char buf2[3]; - buf2[2] = '\0'; - - for (unsigned int i = 0; i < data_size; i++) { - unsigned char c = (unsigned char)data[i]; - buf2[0] = hex_chars[(c & 0xf0) >> 4]; - buf2[1] = hex_chars[c & 0x0f]; - ret.append(buf2); + ret.reserve(data.size() * 2); + for (unsigned char c : data) { + ret.push_back(hex_chars[(c & 0xf0) >> 4]); + ret.push_back(hex_chars[c & 0x0f]); } - return ret; } -static inline std::string hex_encode(std::string_view data) +static inline std::string hex_encode(const char *data, size_t data_size) { - return hex_encode(data.data(), data.size()); + if (!data_size) + return ""; + return hex_encode(std::string_view(data, data_size)); } static inline bool hex_digit_decode(char hexdigit, unsigned char &value) diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index 7dc3d4dea..ddc658cb3 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -6,7 +6,7 @@ #include "log.h" #include "constants.h" // BS, MAP_BLOCKSIZE -#include "noise.h" // PseudoRandom, PcgRandom +#include "noise.h" // PcgRandom #include #include @@ -47,10 +47,7 @@ float myrand_range(float min, float max) } -/* - 64-bit unaligned version of MurmurHash -*/ -u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed) +u64 murmur_hash_64_ua(const void *key, size_t len, unsigned int seed) { const u64 m = 0xc6a4a7935bd1e995ULL; const int r = 47; @@ -90,13 +87,7 @@ u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed) return h; } -/* - blockpos_b: position of block in block coordinates - camera_pos: position of camera in nodes - camera_dir: an unit vector pointing to camera direction - range: viewing range - distance_ptr: return location for distance from the camera -*/ + bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 camera_fov, f32 range, f32 *distance_ptr) { @@ -149,6 +140,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, return true; } + inline float adjustDist(float dist, float zoom_fov) { // 1.775 ~= 72 * PI / 180 * 1.4, the default FOV on the client. diff --git a/src/util/numeric.h b/src/util/numeric.h index 5c0d2cebf..60d86064f 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -115,7 +115,8 @@ inline bool isInArea(v3s16 p, v3s16 d) ); } -inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) +template +inline void sortBoxVerticies(core::vector3d &p1, core::vector3d &p2) { if (p1.X > p2.X) std::swap(p1.X, p2.X); @@ -125,14 +126,18 @@ inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) std::swap(p1.Z, p2.Z); } -inline v3s16 componentwise_min(const v3s16 &a, const v3s16 &b) +template +inline constexpr core::vector3d componentwise_min(const core::vector3d &a, + const core::vector3d &b) { - return v3s16(std::min(a.X, b.X), std::min(a.Y, b.Y), std::min(a.Z, b.Z)); + return {std::min(a.X, b.X), std::min(a.Y, b.Y), std::min(a.Z, b.Z)}; } -inline v3s16 componentwise_max(const v3s16 &a, const v3s16 &b) +template +inline constexpr core::vector3d componentwise_max(const core::vector3d &a, + const core::vector3d &b) { - return v3s16(std::max(a.X, b.X), std::max(a.Y, b.Y), std::max(a.Z, b.Z)); + return {std::max(a.X, b.X), std::max(a.Y, b.Y), std::max(a.Z, b.Z)}; } /// @brief Describes a grid with given step, oirginating at (0,0,0) @@ -277,8 +282,22 @@ inline u32 calc_parity(u32 v) return (0x6996 >> v) & 1; } -u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed); +/** + * Calculate MurmurHash64A hash for an arbitrary block of data. + * @param key data to hash (does not need to be aligned) + * @param len length in bytes + * @param seed initial seed value + * @return hash value + */ +u64 murmur_hash_64_ua(const void *key, size_t len, unsigned int seed); +/** + * @param blockpos_b position of block in block coordinates + * @param camera_pos position of camera in nodes + * @param camera_dir an unit vector pointing to camera direction + * @param range viewing range + * @param distance_ptr return location for distance from the camera + */ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 camera_fov, f32 range, f32 *distance_ptr=NULL); @@ -399,13 +418,6 @@ inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxi } } -inline float cycle_shift(float value, float by = 0, float max = 1) -{ - if (value + by < 0) return value + by + max; - if (value + by > max) return value + by - max; - return value + by; -} - constexpr inline bool is_power_of_two(u32 n) { return n != 0 && (n & (n - 1)) == 0; @@ -469,31 +481,40 @@ inline v3f getPitchYawRoll(const core::matrix4 &m) } // Muliply the RGB value of a color linearly, and clamp to black/white -inline irr::video::SColor multiplyColorValue(const irr::video::SColor &color, float mod) +inline video::SColor multiplyColorValue(const video::SColor &color, float mod) { - return irr::video::SColor(color.getAlpha(), + return video::SColor(color.getAlpha(), core::clamp(color.getRed() * mod, 0, 255), core::clamp(color.getGreen() * mod, 0, 255), core::clamp(color.getBlue() * mod, 0, 255)); } -template inline T numericAbsolute(T v) { return v < 0 ? T(-v) : v; } -template inline T numericSign(T v) { return T(v < 0 ? -1 : (v == 0 ? 0 : 1)); } - -inline v3f vecAbsolute(v3f v) +template constexpr inline T numericAbsolute(T v) { - return v3f( + return v < 0 ? T(-v) : v; +} + +template constexpr inline T numericSign(T v) +{ + return T(v < 0 ? -1 : (v == 0 ? 0 : 1)); +} + +template +inline constexpr core::vector3d vecAbsolute(const core::vector3d &v) +{ + return { numericAbsolute(v.X), numericAbsolute(v.Y), numericAbsolute(v.Z) - ); + }; } -inline v3f vecSign(v3f v) +template +inline constexpr core::vector3d vecSign(const core::vector3d &v) { - return v3f( + return { numericSign(v.X), numericSign(v.Y), numericSign(v.Z) - ); + }; } diff --git a/src/util/pointer.h b/src/util/pointer.h index 957277a40..fe90a3866 100644 --- a/src/util/pointer.h +++ b/src/util/pointer.h @@ -11,7 +11,8 @@ #include -template class ConstSharedPtr { +template +class ConstSharedPtr { public: ConstSharedPtr(T *ptr) : ptr(ptr) {} ConstSharedPtr(const std::shared_ptr &ptr) : ptr(ptr) {} @@ -33,7 +34,7 @@ public: m_size = 0; data = nullptr; } - Buffer(unsigned int size) + Buffer(size_t size) { m_size = size; if (size != 0) { @@ -59,7 +60,7 @@ public: } } // Copies whole buffer - Buffer(const T *t, unsigned int size) + Buffer(const T *t, size_t size) { m_size = size; if (size != 0) { @@ -77,9 +78,8 @@ public: Buffer& operator=(Buffer &&buffer) { - if (this == &buffer) { + if (this == &buffer) return *this; - } drop(); m_size = buffer.m_size; if (m_size != 0) { @@ -104,7 +104,7 @@ public: } } - T & operator[](unsigned int i) const + T & operator[](size_t i) const { return data[i]; } @@ -113,7 +113,7 @@ public: return data; } - unsigned int getSize() const + size_t getSize() const { return m_size; } @@ -132,7 +132,7 @@ private: delete[] data; } T *data; - unsigned int m_size; + size_t m_size; }; /************************************************ @@ -149,11 +149,12 @@ public: SharedBuffer() { m_size = 0; - data = NULL; - refcount = new unsigned int; + data = nullptr; + refcount = new u32; (*refcount) = 1; } - SharedBuffer(unsigned int size) + + SharedBuffer(size_t size) { m_size = size; if (m_size != 0) { @@ -162,10 +163,11 @@ public: data = nullptr; } - refcount = new unsigned int; + refcount = new u32; memset(data, 0, sizeof(T) * m_size); (*refcount) = 1; } + SharedBuffer(const SharedBuffer &buffer) { m_size = buffer.m_size; @@ -173,12 +175,11 @@ public: refcount = buffer.refcount; (*refcount)++; } - SharedBuffer & operator=(const SharedBuffer & buffer) - { - if (this == &buffer) { - return *this; - } + SharedBuffer & operator=(const SharedBuffer &buffer) + { + if (this == &buffer) + return *this; drop(); m_size = buffer.m_size; data = buffer.data; @@ -186,8 +187,9 @@ public: (*refcount)++; return *this; } + //! Copies whole buffer - SharedBuffer(const T *t, unsigned int size) + SharedBuffer(const T *t, size_t size) { m_size = size; if (m_size != 0) { @@ -196,34 +198,41 @@ public: } else { data = nullptr; } - refcount = new unsigned int; + refcount = new u32; (*refcount) = 1; } + //! Copies whole buffer SharedBuffer(const Buffer &buffer) : SharedBuffer(*buffer, buffer.getSize()) { } + ~SharedBuffer() { drop(); } - T & operator[](unsigned int i) const + + T & operator[](size_t i) const { assert(i < m_size); return data[i]; } + T * operator*() const { return data; } - unsigned int getSize() const + + size_t getSize() const { return m_size; } + operator Buffer() const { return Buffer(data, m_size); } + private: void drop() { @@ -234,9 +243,10 @@ private: delete refcount; } } + T *data; - unsigned int m_size; - unsigned int *refcount; + size_t m_size; + u32 *refcount; }; // This class is not thread-safe! diff --git a/src/util/serialize.h b/src/util/serialize.h index c2cfa601d..b12d551ac 100644 --- a/src/util/serialize.h +++ b/src/util/serialize.h @@ -48,8 +48,8 @@ // not represent the full range, but rather the largest safe range, of values on // all supported architectures. Note: This definition makes assumptions on // platform float-to-int conversion behavior. -#define F1000_MIN ((float)(s32)((float)(-0x7FFFFFFF - 1) / FIXEDPOINT_FACTOR)) -#define F1000_MAX ((float)(s32)((float)(0x7FFFFFFF) / FIXEDPOINT_FACTOR)) +static constexpr float F1000_MIN = (s32)((float)(S32_MIN) / FIXEDPOINT_FACTOR); +static constexpr float F1000_MAX = (s32)((float)(S32_MAX) / FIXEDPOINT_FACTOR); #define STRING_MAX_LEN 0xFFFF #define WIDE_STRING_MAX_LEN 0xFFFF @@ -159,7 +159,7 @@ inline void writeU64(u8 *data, u64 i) inline u8 readU8(const u8 *data) { - return ((u8)data[0] << 0); + return data[0]; } inline s8 readS8(const u8 *data) diff --git a/src/util/sha1.cpp b/src/util/sha1.cpp index 5d8b92598..850c7201d 100644 --- a/src/util/sha1.cpp +++ b/src/util/sha1.cpp @@ -29,37 +29,29 @@ SOFTWARE. #include #include +#define IN_SHA1_CPP + #include "sha1.h" -// print out memory in hexadecimal -void SHA1::hexPrinter( unsigned char* c, int l ) -{ - assert( c ); - assert( l > 0 ); - while( l > 0 ) - { - printf( " %02x", *c ); - l--; - c++; - } -} +namespace { // circular left bit rotation. MSB wraps around to LSB -Uint32 SHA1::lrot( Uint32 x, int bits ) +inline Uint32 lrot( Uint32 x, int bits ) { return (x<>(32 - bits)); -}; +} // Save a 32-bit unsigned integer to memory, in big-endian order -void SHA1::storeBigEndianUint32( unsigned char* byte, Uint32 num ) +inline void storeBigEndianUint32( unsigned char* byte, Uint32 num ) { - assert( byte ); byte[0] = (unsigned char)(num>>24); byte[1] = (unsigned char)(num>>16); byte[2] = (unsigned char)(num>>8); byte[3] = (unsigned char)num; } +} + // Constructor ******************************************************* SHA1::SHA1() @@ -81,7 +73,6 @@ SHA1::~SHA1() void SHA1::process() { assert( unprocessedBytes == 64 ); - //printf( "process: " ); hexPrinter( bytes, 64 ); printf( "\n" ); int t; Uint32 a, b, c, d, e, K, f, W[80]; // starting values diff --git a/src/util/sha1.h b/src/util/sha1.h index 81eeeca97..39c72f2da 100644 --- a/src/util/sha1.h +++ b/src/util/sha1.h @@ -26,6 +26,10 @@ SOFTWARE. #pragma once +#if !defined(IN_HASHING_CPP) && !defined(IN_SHA1_CPP) +#error do not include directly +#endif + #include #include #include @@ -59,9 +63,4 @@ public: getDigest(reinterpret_cast(ret.data())); return ret; } - - // utility methods - static Uint32 lrot(Uint32 x, int bits); - static void storeBigEndianUint32(unsigned char *byte, Uint32 num); - static void hexPrinter(unsigned char *c, int l); }; diff --git a/src/util/srp.h b/src/util/srp.h index fc4d2dc89..7cbfe3a19 100644 --- a/src/util/srp.h +++ b/src/util/srp.h @@ -55,6 +55,8 @@ #pragma once +#include + struct SRPVerifier; struct SRPUser; diff --git a/src/util/string.cpp b/src/util/string.cpp index c08421d55..e06990356 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -189,35 +189,37 @@ std::string urlencode(std::string_view str) // Encodes reserved URI characters by a percent sign // followed by two hex digits. See RFC 3986, section 2.3. static const char url_hex_chars[] = "0123456789ABCDEF"; - std::ostringstream oss(std::ios::binary); + std::string ret; + ret.reserve(str.size()); for (unsigned char c : str) { if (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~') { - oss << c; + ret.push_back(c); } else { - oss << "%" - << url_hex_chars[(c & 0xf0) >> 4] - << url_hex_chars[c & 0x0f]; + ret.push_back('%'); + ret.push_back(url_hex_chars[(c & 0xf0) >> 4]); + ret.push_back(url_hex_chars[c & 0x0f]); } } - return oss.str(); + return ret; } std::string urldecode(std::string_view str) { // Inverse of urlencode - std::ostringstream oss(std::ios::binary); + std::string ret; + ret.reserve(str.size()); for (u32 i = 0; i < str.size(); i++) { unsigned char highvalue, lowvalue; - if (str[i] == '%' && + if (str[i] == '%' && i+2 < str.size() && hex_digit_decode(str[i+1], highvalue) && hex_digit_decode(str[i+2], lowvalue)) { - oss << (char) ((highvalue << 4) | lowvalue); + ret.push_back(static_cast((highvalue << 4) | lowvalue)); i += 2; } else { - oss << str[i]; + ret.push_back(str[i]); } } - return oss.str(); + return ret; } u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask) @@ -318,7 +320,7 @@ char *mystrtok_r(char *s, const char *sep, char **lasts) noexcept u64 read_seed(const char *str) { - char *endptr; + char *endptr = nullptr; u64 num; if (str[0] == '0' && str[1] == 'x') @@ -327,7 +329,7 @@ u64 read_seed(const char *str) num = strtoull(str, &endptr, 10); if (*endptr) - num = murmur_hash_64_ua(str, (int)strlen(str), 0x1337); + num = murmur_hash_64_ua(str, strlen(str), 0x1337); return num; } diff --git a/src/util/string.h b/src/util/string.h index 8b0848f8e..d57a7baa9 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -86,7 +86,9 @@ std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask); size_t mystrlcpy(char *dst, const char *src, size_t size) noexcept; char *mystrtok_r(char *s, const char *sep, char **lasts) noexcept; +/// @brief turn string into a map seed. either directly if it's a number or by hashing it. u64 read_seed(const char *str); + bool parseColorString(const std::string &value, video::SColor &color, bool quiet, unsigned char default_alpha = 0xff); std::string encodeHexColorString(video::SColor color); @@ -330,7 +332,7 @@ inline bool my_isspace(const wchar_t c) * @return A view of \p str with leading and trailing whitespace removed. */ template -inline std::basic_string_view trim(const std::basic_string_view &str) +inline std::basic_string_view trim(std::basic_string_view str) { size_t front = 0; size_t back = str.size(); diff --git a/src/util/thread.h b/src/util/thread.h index 8b28bf72e..857a341be 100644 --- a/src/util/thread.h +++ b/src/util/thread.h @@ -18,6 +18,9 @@ public: MutexedVariable(const T &value): m_value(value) {} + MutexedVariable(T &&value): + m_value(std::move(value)) + {} T get() { @@ -31,9 +34,14 @@ public: m_value = value; } - // You pretty surely want to grab the lock when accessing this - T m_value; + void set(T &&value) + { + MutexAutoLock lock(m_mutex); + m_value = std::move(value); + } + private: + T m_value; std::mutex m_mutex; };