From cd831e6d4b94b48e01050e1e9c35105dd7ef5834 Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Tue, 14 Dec 2021 14:33:58 +0100 Subject: Commented out unused Base64 decoding table --- zencore/base64.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zencore/base64.cpp b/zencore/base64.cpp index 9a6ea3b75..0448d7c2f 100644 --- a/zencore/base64.cpp +++ b/zencore/base64.cpp @@ -11,6 +11,7 @@ static const uint8_t EncodingAlphabet[64] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; /** The table used to convert an ascii character into a 6 bit value */ +#if 0 static const uint8_t DecodingAlphabet[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x00-0x0f 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x10-0x1f @@ -29,6 +30,7 @@ static const uint8_t DecodingAlphabet[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xe0-0xef 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 0xf0-0xff }; +#endif // 0 template uint32_t -- cgit v1.2.3 From 05e92c2d0ffbc3c0e653ed6328f39058d38d4e6f Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Tue, 14 Dec 2021 14:34:14 +0100 Subject: Use zen::Min() instead of std::min() Some compilers will struggle to deduce the template type for calls to std::min() while others are more complicit. The can easliy lead to unexpected compile errors on a platform. --- zencore/include/zencore/memory.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zencore/include/zencore/memory.h b/zencore/include/zencore/memory.h index aba391c85..313813af9 100644 --- a/zencore/include/zencore/memory.h +++ b/zencore/include/zencore/memory.h @@ -128,7 +128,7 @@ struct MutableMemoryView } /** Modifies the view to be the given number of bytes from the left. */ - constexpr inline void LeftInline(uint64_t InSize) { m_DataEnd = std::min(m_DataEnd, m_Data + InSize); } + constexpr inline void LeftInline(uint64_t InSize) { m_DataEnd = zen::Min(m_DataEnd, m_Data + InSize); } /** Modifies the view to be the middle part by taking up to the given number of bytes from the given offset. */ inline void MidInline(uint64_t InOffset, uint64_t InSize = ~uint64_t(0)) @@ -217,7 +217,7 @@ struct MemoryView /** Modifies the view by chopping the given number of bytes from the left. */ inline void RightChopInline(uint64_t InSize) { - const uint64_t Offset = std::min(GetSize(), InSize); + const uint64_t Offset = zen::Min(GetSize(), InSize); m_Data = GetDataAtOffsetNoCheck(Offset); } @@ -257,7 +257,7 @@ struct MemoryView inline void LeftInline(uint64_t InSize) { InSize = zen::Min(GetSize(), InSize); - m_DataEnd = std::min(m_DataEnd, m_Data + InSize); + m_DataEnd = zen::Min(m_DataEnd, m_Data + InSize); } /** Modifies the view to be the middle part by taking up to the given number of bytes from the given offset. */ -- cgit v1.2.3 From 3de8a7abe981d590c1b7db162f3b2250460adaea Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Tue, 14 Dec 2021 14:55:45 +0100 Subject: Wrapped direct use of C++20 library concepts Some C++ libraries do not fully support concepts in the versions that are available by default on Linux and MacOS. The compilers do support them though so we can still apply concepts/requires to templates --- zencore/include/zencore/intmath.h | 4 ++-- zencore/include/zencore/refcount.h | 2 +- zencore/include/zencore/sharedbuffer.h | 2 +- zencore/include/zencore/stats.h | 2 +- zencore/include/zencore/string.h | 6 +++--- zencore/include/zencore/zencore.h | 23 +++++++++++++++++++++++ 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/zencore/include/zencore/intmath.h b/zencore/include/zencore/intmath.h index 0d0ceff16..b4a0b6796 100644 --- a/zencore/include/zencore/intmath.h +++ b/zencore/include/zencore/intmath.h @@ -59,7 +59,7 @@ IsPow2(uint64_t n) } /// Round an integer up to the closest integer multiplier of 'base' ('base' must be a power of two) -template +template T RoundUp(T Value, auto Base) { @@ -68,7 +68,7 @@ RoundUp(T Value, auto Base) } bool -IsMultipleOf(std::integral auto Value, auto MultiplierPow2) +IsMultipleOf(Integral auto Value, auto MultiplierPow2) { ZEN_ASSERT_SLOW(IsPow2(MultiplierPow2)); return (Value & (MultiplierPow2 - 1)) == 0; diff --git a/zencore/include/zencore/refcount.h b/zencore/include/zencore/refcount.h index e8a3095f9..5c8b70ef6 100644 --- a/zencore/include/zencore/refcount.h +++ b/zencore/include/zencore/refcount.h @@ -118,7 +118,7 @@ public: inline ~Ref() { m_Ref && m_Ref->Release(); } template - requires std::derived_from + requires DerivedFrom inline Ref(const Ref& Rhs) : Ref(Rhs.m_Ref) {} [[nodiscard]] inline bool IsNull() const { return m_Ref == nullptr; } diff --git a/zencore/include/zencore/sharedbuffer.h b/zencore/include/zencore/sharedbuffer.h index 1f87dc639..97c5a9d21 100644 --- a/zencore/include/zencore/sharedbuffer.h +++ b/zencore/include/zencore/sharedbuffer.h @@ -144,7 +144,7 @@ public: /** Make a non-owned view of the input */ [[nodiscard]] inline static SharedBuffer MakeView(MemoryView View) { return MakeView(View.GetData(), View.GetSize()); } /** Make a non-owning view of the memory of the contiguous container. */ - [[nodiscard]] inline static SharedBuffer MakeView(const std::ranges::contiguous_range auto& Container) + [[nodiscard]] inline static SharedBuffer MakeView(const ContiguousRange auto& Container) { std::span Span = Container; return MakeView(Span.data(), Span.size() * sizeof(typename decltype(Span)::element_type)); diff --git a/zencore/include/zencore/stats.h b/zencore/include/zencore/stats.h index d58435a20..f0efc36d8 100644 --- a/zencore/include/zencore/stats.h +++ b/zencore/include/zencore/stats.h @@ -142,7 +142,7 @@ public: void Update(int64_t Value); SampleSnapshot Snapshot() const; - template T> + template T> void IterateValues(T Callback) const { for (const auto& Value : m_Values) diff --git a/zencore/include/zencore/string.h b/zencore/include/zencore/string.h index 848310aa3..df78b2757 100644 --- a/zencore/include/zencore/string.h +++ b/zencore/include/zencore/string.h @@ -74,8 +74,8 @@ protected: struct IntNum : public TextNumBase { - inline IntNum(std::unsigned_integral auto Number) { ToString(m_Buffer, uint64_t(Number)); } - inline IntNum(std::signed_integral auto Number) { ToString(m_Buffer, int64_t(Number)); } + inline IntNum(UnsignedIntegral auto Number) { ToString(m_Buffer, uint64_t(Number)); } + inline IntNum(SignedIntegral auto Number) { ToString(m_Buffer, int64_t(Number)); } }; ////////////////////////////////////////////////////////////////////////// @@ -602,7 +602,7 @@ NiceRate(uint64_t Num, uint32_t DurationMilliseconds, const char* Unit = "B") ////////////////////////////////////////////////////////////////////////// -template +template std::optional ParseInt(const std::string_view& Input) { diff --git a/zencore/include/zencore/zencore.h b/zencore/include/zencore/zencore.h index 3352af5d2..8688ddc13 100644 --- a/zencore/include/zencore/zencore.h +++ b/zencore/include/zencore/zencore.h @@ -5,6 +5,7 @@ #include #include #include +#include #ifndef ZEN_WITH_TESTS # define ZEN_WITH_TESTS 1 @@ -119,6 +120,28 @@ } while (0) #endif +// At the time of writing only ver >= 13 of LLVM's libc++ has an implementation +// of std::integral. Some platforms like Ubuntu and Mac OS are still on 12. +#if defined(__cpp_lib_concepts) + template concept Integral = std::integral; + template concept SignedIntegral = std::signed_integral; + template concept UnsignedIntegral = std::unsigned_integral; + template concept Invocable = std::invocable; + template concept DerivedFrom = std::derived_from; +#else + template concept Integral = std::is_integral_v; + template concept SignedIntegral = Integral && std::is_signed_v; + template concept UnsignedIntegral = Integral && !std::is_signed_v; + template concept Invocable = true; + template concept DerivedFrom = std::is_base_of_v && std::is_convertible_v; +#endif + +#if defined(__cpp_lib_ranges) + template concept ContiguousRange = std::ranges::contiguous_range; +#else + template concept ContiguousRange = true; +#endif + ////////////////////////////////////////////////////////////////////////// // Architecture // -- cgit v1.2.3 From fe9838c6e1fc00805ee2fcd5c50feea4f28bb08c Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Tue, 14 Dec 2021 14:57:33 +0100 Subject: Deleted unused include --- zencore/include/zencore/memory.h | 1 - 1 file changed, 1 deletion(-) diff --git a/zencore/include/zencore/memory.h b/zencore/include/zencore/memory.h index 313813af9..df53d0c60 100644 --- a/zencore/include/zencore/memory.h +++ b/zencore/include/zencore/memory.h @@ -7,7 +7,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From 8b013702277fa813a838a6b55d7506c81ca1f1ac Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Wed, 15 Dec 2021 13:40:58 +0100 Subject: Compile out source_location use if the toolchain doesn't support it --- zencore/except.cpp | 2 +- zencore/include/zencore/except.h | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/zencore/except.cpp b/zencore/except.cpp index ebaecf815..fae629286 100644 --- a/zencore/except.cpp +++ b/zencore/except.cpp @@ -81,7 +81,7 @@ GetSystemErrorAsString(uint32_t ErrorCode) return std::error_code(ErrorCode, std::system_category()).message(); } -#if __cpp_lib_source_location +#if defined(__cpp_lib_source_location) void ThrowLastError(std::string_view Message, const std::source_location& Location) { diff --git a/zencore/include/zencore/except.h b/zencore/include/zencore/except.h index e0e4aaae0..6719c1319 100644 --- a/zencore/include/zencore/except.h +++ b/zencore/include/zencore/except.h @@ -8,7 +8,9 @@ #else # include #endif -#include +#if __has_include("source_location") +# include +#endif #include #include @@ -20,7 +22,7 @@ ZENCORE_API void ThrowSystemException [[noreturn]] (HRESULT hRes, std::string_vi ZENCORE_API void ThrowLastError [[noreturn]] (std::string_view Message); -#if __cpp_lib_source_location +#if defined(__cpp_lib_source_location) ZENCORE_API void ThrowLastError [[noreturn]] (std::string_view Message, const std::source_location& Location); #endif -- cgit v1.2.3 From a6101a0cfea738cb623a77aa383548e00303907f Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Wed, 15 Dec 2021 13:41:45 +0100 Subject: Copy/paste errors in MD5 from SHA1 --- zencore/include/zencore/md5.h | 6 +++--- zencore/md5.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zencore/include/zencore/md5.h b/zencore/include/zencore/md5.h index 4ed4f6c56..d934dd86b 100644 --- a/zencore/include/zencore/md5.h +++ b/zencore/include/zencore/md5.h @@ -16,19 +16,19 @@ struct MD5 inline auto operator<=>(const MD5& rhs) const = default; - static const int StringLength = 40; + static const int StringLength = 32; typedef char String_t[StringLength + 1]; static MD5 HashMemory(const void* data, size_t byteCount); static MD5 FromHexString(const char* string); - const char* ToHexString(char* outString /* 40 characters + NUL terminator */) const; + const char* ToHexString(char* outString /* 32 characters + NUL terminator */) const; StringBuilderBase& ToHexString(StringBuilderBase& outBuilder) const; static MD5 Zero; // Initialized to all zeroes }; /** - * Utility class for computing SHA1 hashes + * Utility class for computing MD5 hashes */ class MD5Stream { diff --git a/zencore/md5.cpp b/zencore/md5.cpp index 237f6cfdd..519e41f37 100644 --- a/zencore/md5.cpp +++ b/zencore/md5.cpp @@ -401,7 +401,7 @@ MD5::FromHexString(const char* string) } const char* -MD5::ToHexString(char* outString /* 40 characters + NUL terminator */) const +MD5::ToHexString(char* outString /* 32 characters + NUL terminator */) const { ToHexBytes(Hash, sizeof(MD5), outString); outString[2 * sizeof(MD5)] = '\0'; -- cgit v1.2.3 From 33f709ea4e3c6452a4d307d158c88623f899edb4 Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Wed, 15 Dec 2021 13:42:38 +0100 Subject: Not all compilers support C++20's iterator string_view contructor --- zencore/include/zencore/string.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zencore/include/zencore/string.h b/zencore/include/zencore/string.h index df78b2757..dba6843cf 100644 --- a/zencore/include/zencore/string.h +++ b/zencore/include/zencore/string.h @@ -665,8 +665,8 @@ template uint32_t ForEachStrTok(const std::string_view& Str, char Delim, Fn&& Func) { - auto It = Str.begin(); - auto End = Str.end(); + const char* It = Str.data(); + const char* End = It + Str.length(); uint32_t Count = 0; while (It != End) @@ -677,7 +677,7 @@ ForEachStrTok(const std::string_view& Str, char Delim, Fn&& Func) continue; } - std::string_view Remaining{It, End}; + std::string_view Remaining{It, size_t(ptrdiff_t(End - It))}; size_t Idx = Remaining.find(Delim, 0); if (Idx == std::string_view::npos) @@ -686,7 +686,7 @@ ForEachStrTok(const std::string_view& Str, char Delim, Fn&& Func) } Count++; - std::string_view Token{It, It + Idx}; + std::string_view Token{It, Idx}; if (!Func(Token)) { break; -- cgit v1.2.3 From 8716d8f7bc8207b38defeb464c42e8d572816248 Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Wed, 15 Dec 2021 13:43:16 +0100 Subject: Deleted unused endian.h include --- zencore/md5.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/zencore/md5.cpp b/zencore/md5.cpp index 519e41f37..bf11a6b3a 100644 --- a/zencore/md5.cpp +++ b/zencore/md5.cpp @@ -7,11 +7,6 @@ #include -// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN -#ifndef _MSC_VER -# include -#endif - /* ********************************************************************** ** md5.h -- Header file for implementation of MD5 ** -- cgit v1.2.3 From e7a7c5b3295e50df0018f3429e2b20729cb08f2f Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Wed, 15 Dec 2021 13:43:30 +0100 Subject: Added MD5 tests --- zencore/md5.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/zencore/md5.cpp b/zencore/md5.cpp index bf11a6b3a..a5a5ea41d 100644 --- a/zencore/md5.cpp +++ b/zencore/md5.cpp @@ -6,6 +6,7 @@ #include #include +#include /* ********************************************************************** @@ -438,6 +439,23 @@ toString(const MD5& value) TEST_CASE("MD5") { + using namespace std::literals; + + auto Input = "jumblesmcgee"sv; + auto Output = "28f2200a59c60b75947099d750c2cc50"sv; + + MD5Stream Stream; + Stream.Append(Input.data(), Input.length()); + MD5 Result = Stream.GetHash(); + + MD5::String_t Buffer; + Result.ToHexString(Buffer); + + CHECK(Output.compare(Buffer)); + + MD5 Reresult = MD5::FromHexString(Buffer); + Reresult.ToHexString(Buffer); + CHECK(Output.compare(Buffer)); } #endif -- cgit v1.2.3 From 920c0845d299e4c5c2a8b5cfe4dcc3a99c35e87b Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Wed, 15 Dec 2021 15:27:12 +0100 Subject: Thread naming for Mac --- zencore/thread.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zencore/thread.cpp b/zencore/thread.cpp index 6d17e6968..9e35e5d57 100644 --- a/zencore/thread.cpp +++ b/zencore/thread.cpp @@ -88,8 +88,12 @@ SetCurrentThreadName([[maybe_unused]] std::string_view ThreadName) SetNameInternal(GetCurrentThreadId(), ThreadNameZ.c_str()); #else std::string ThreadNameZ{ThreadName}; +#if ZEN_PLATFORM_MAC + pthread_setname_np(ThreadNameZ.c_str()); +#else pthread_setname_np(pthread_self(), ThreadNameZ.c_str()); #endif +#endif } // namespace zen void -- cgit v1.2.3 From 7a821d1d95298e4dec60733454856a93140cd73e Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Wed, 15 Dec 2021 15:27:37 +0100 Subject: GetThreadId() for Mac --- zencore/thread.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zencore/thread.cpp b/zencore/thread.cpp index 9e35e5d57..8fe25b528 100644 --- a/zencore/thread.cpp +++ b/zencore/thread.cpp @@ -1041,8 +1041,10 @@ GetCurrentThreadId() { #if ZEN_PLATFORM_WINDOWS return ::GetCurrentThreadId(); -#else +#elif ZEN_PLATFORM_LINUX return int(gettid()); +#elif ZEN_PLATFORM_MAC + return int(pthread_mach_thread_np(pthread_self())); #endif } -- cgit v1.2.3 From 130b8875ff43a6744fa097472fbce03a36ff97d7 Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Thu, 16 Dec 2021 09:29:26 +0100 Subject: Only Linux has an endian.h --- zencore/sha1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zencore/sha1.cpp b/zencore/sha1.cpp index 8b4e7897f..66e01f232 100644 --- a/zencore/sha1.cpp +++ b/zencore/sha1.cpp @@ -12,7 +12,7 @@ #include // big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN -#ifndef _MSC_VER +#if ZEN_PLATFORM_LINUX # include #endif -- cgit v1.2.3 From 04fb698644c6ced1fef16c2114234576b4219020 Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Thu, 16 Dec 2021 09:29:50 +0100 Subject: Use a CAS loop if atomic::fetch_add() isn't available --- zencore/stats.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/zencore/stats.cpp b/zencore/stats.cpp index 1bb6f6de0..595c45c3f 100644 --- a/zencore/stats.cpp +++ b/zencore/stats.cpp @@ -46,7 +46,19 @@ RawEWMA::Tick(double Alpha, uint64_t Interval, uint64_t Count, bool IsInitialUpd } else { - m_Rate.fetch_add(Alpha * (InstantRate - m_Rate)); + double Delta = Alpha * (InstantRate - m_Rate); + +#if defined(__cpp_lib_atomic_float) + m_Rate.fetch_add(Delta); +#else + double Value = m_Rate.load(std::memory_order_acquire); + double Next; + do + { + Next = Value + Delta; + } + while (!m_Rate.compare_exchange_weak(Value, Next, std::memory_order_relaxed)); +#endif } } -- cgit v1.2.3