aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-06-30 11:07:10 +0200
committerStefan Boberg <[email protected]>2023-06-30 11:07:10 +0200
commit0396f400a97f71bf743d584acc71a0cdbc155566 (patch)
tree829f7764157aecf9c198e4b076e5fb1adcfeb13f /src
parentvarious zenhttp fixes from sb/proto (diff)
downloadzen-0396f400a97f71bf743d584acc71a0cdbc155566.tar.xz
zen-0396f400a97f71bf743d584acc71a0cdbc155566.zip
* Added Guid::FromString
* Added LoadCompactBinaryObject from file to compactbinaryfile.cpp/h * Added SaveCompactBinary(BinaryWriter& Ar, ...) functions * Added ZEN_PLATFORM_NAME define * Added SystemMetrics functionality to query system properties (see zencore/system.h)
Diffstat (limited to 'src')
-rw-r--r--src/zencore/compactbinary.cpp48
-rw-r--r--src/zencore/compactbinaryfile.cpp33
-rw-r--r--src/zencore/filesystem.cpp69
-rw-r--r--src/zencore/include/zencore/compactbinary.h14
-rw-r--r--src/zencore/include/zencore/compactbinarybuilder.h4
-rw-r--r--src/zencore/include/zencore/compactbinaryfile.h18
-rw-r--r--src/zencore/include/zencore/filesystem.h10
-rw-r--r--src/zencore/include/zencore/fmtutils.h19
-rw-r--r--src/zencore/include/zencore/guid.h26
-rw-r--r--src/zencore/include/zencore/iobuffer.h1
-rw-r--r--src/zencore/include/zencore/iohash.h3
-rw-r--r--src/zencore/include/zencore/string.h11
-rw-r--r--src/zencore/include/zencore/system.h37
-rw-r--r--src/zencore/include/zencore/thread.h5
-rw-r--r--src/zencore/include/zencore/uid.h2
-rw-r--r--src/zencore/include/zencore/zencore.h9
-rw-r--r--src/zencore/session.cpp4
-rw-r--r--src/zencore/system.cpp199
-rw-r--r--src/zencore/testing.cpp10
-rw-r--r--src/zencore/thread.cpp2
-rw-r--r--src/zencore/uid.cpp3
-rw-r--r--src/zencore/xmake.lua1
22 files changed, 490 insertions, 38 deletions
diff --git a/src/zencore/compactbinary.cpp b/src/zencore/compactbinary.cpp
index 0db9f02ea..5b599dda3 100644
--- a/src/zencore/compactbinary.cpp
+++ b/src/zencore/compactbinary.cpp
@@ -358,6 +358,34 @@ Guid::ToString(StringBuilderBase& Sb) const
return Sb;
}
+Guid
+Guid::FromString(std::string_view InString)
+{
+ if (InString.size() != 36)
+ {
+ }
+
+ bool Ok = true;
+
+ uint32_t V0 = 0, V5 = 0;
+ uint16_t V1 = 0, V2 = 0, V3 = 0, V4 = 0;
+
+ Ok = Ok && ParseHexNumber(InString.substr(0, 8), /* out */ V0);
+ Ok = Ok && ParseHexNumber(InString.substr(9, 4), /* out */ V1);
+ Ok = Ok && ParseHexNumber(InString.substr(14, 4), /* out */ V2);
+ Ok = Ok && ParseHexNumber(InString.substr(19, 4), /* out */ V3);
+ Ok = Ok && ParseHexNumber(InString.substr(24, 4), /* out */ V4);
+ Ok = Ok && ParseHexNumber(InString.substr(28, 8), /* out */ V5);
+
+ Guid Value;
+ Value.A = V0;
+ Value.B = V1 << 16 | V2;
+ Value.C = V3 << 16 | V4;
+ Value.D = V5;
+
+ return Value;
+}
+
//////////////////////////////////////////////////////////////////////////
namespace CompactBinaryPrivate {
@@ -1943,6 +1971,22 @@ uson_forcelink()
{
}
+TEST_CASE("guid")
+{
+ using namespace std::literals;
+
+ const Guid A = Guid::FromString("03000c43-d267-36fd-9164-a7555824822b"sv);
+
+ StringBuilder<40> GuidStr;
+ A.ToString(GuidStr);
+
+ CHECK(std::string_view(GuidStr) == "03000c43-d267-36fd-9164-a7555824822b"sv);
+
+ const Guid B = Guid::FromString(GuidStr);
+
+ CHECK(A == B);
+}
+
TEST_CASE("uson")
{
using namespace std::literals;
@@ -2142,8 +2186,8 @@ TEST_CASE("uson.json")
SUBCASE("number.nan")
{
- const float FloatNan = std::numeric_limits<float>::quiet_NaN();
- const double DoubleNan = std::numeric_limits<double>::quiet_NaN();
+ constexpr float FloatNan = std::numeric_limits<float>::quiet_NaN();
+ constexpr double DoubleNan = std::numeric_limits<double>::quiet_NaN();
CbObjectWriter Writer;
Writer << "FloatNan" << FloatNan;
diff --git a/src/zencore/compactbinaryfile.cpp b/src/zencore/compactbinaryfile.cpp
new file mode 100644
index 000000000..f2121a0bd
--- /dev/null
+++ b/src/zencore/compactbinaryfile.cpp
@@ -0,0 +1,33 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include "zencore/compactbinaryfile.h"
+#include "zencore/compactbinaryvalidation.h"
+
+#include <zencore/filesystem.h>
+
+namespace zen {
+
+CbObjectFromFile
+LoadCompactBinaryObject(const std::filesystem::path& FilePath)
+{
+ FileContents ObjectFile = ReadFile(FilePath);
+
+ if (ObjectFile.ErrorCode)
+ {
+ throw std::system_error(ObjectFile.ErrorCode);
+ }
+
+ IoBuffer ObjectBuffer = ObjectFile.Flatten();
+
+ if (CbValidateError Result = ValidateCompactBinary(ObjectBuffer, CbValidateMode::All); Result == CbValidateError::None)
+ {
+ CbObject Object = LoadCompactBinaryObject(ObjectBuffer);
+ const IoHash WorkerId = IoHash::HashBuffer(ObjectBuffer);
+
+ return {.Object = Object, .Hash = WorkerId};
+ }
+
+ return {.Hash = IoHash::Zero};
+}
+
+} // namespace zen
diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp
index cde4c52ab..059d1b5f0 100644
--- a/src/zencore/filesystem.cpp
+++ b/src/zencore/filesystem.cpp
@@ -2,6 +2,7 @@
#include <zencore/filesystem.h>
+#include <zencore/compositebuffer.h>
#include <zencore/except.h>
#include <zencore/fmtutils.h>
#include <zencore/iobuffer.h>
@@ -100,6 +101,8 @@ WipeDirectory(const wchar_t* DirPath)
WIN32_FIND_DATAW FindData;
HANDLE hFind = FindFirstFileW(Pattern.c_str(), &FindData);
+ bool Success = true;
+
if (hFind != nullptr)
{
do
@@ -135,27 +138,43 @@ WipeDirectory(const wchar_t* DirPath)
{
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_RECALL_ON_OPEN)
{
- DeleteReparsePoint(Path.c_str(), FindData.dwReserved0);
+ if (!DeleteReparsePoint(Path.c_str(), FindData.dwReserved0))
+ {
+ Success = false;
+ }
}
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS)
{
- DeleteReparsePoint(Path.c_str(), FindData.dwReserved0);
+ if (!DeleteReparsePoint(Path.c_str(), FindData.dwReserved0))
+ {
+ Success = false;
+ }
}
- bool Success = DeleteDirectories(Path.c_str());
+ bool Succeeded = DeleteDirectories(Path.c_str());
- if (!Success)
+ if (!Succeeded)
{
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
{
- DeleteReparsePoint(Path.c_str(), FindData.dwReserved0);
+ if (!DeleteReparsePoint(Path.c_str(), FindData.dwReserved0))
+ {
+ Success = false;
+ }
}
}
}
else
{
- DeleteFileW(Path.c_str());
+ BOOL Succeeded = DeleteFileW(Path.c_str());
+
+ if (!Succeeded)
+ {
+ // We should emit a warning here, but this is quite low level so care
+ // needs to be taken.
+ Success = false;
+ }
}
}
} while (FindNextFileW(hFind, &FindData) == TRUE);
@@ -633,6 +652,26 @@ WriteFile(std::filesystem::path Path, IoBuffer Data)
WriteFile(Path, &DataPtr, 1);
}
+void
+WriteFile(std::filesystem::path Path, CompositeBuffer InData)
+{
+ std::vector<IoBuffer> DataVec;
+
+ for (const SharedBuffer& Segment : InData.GetSegments())
+ {
+ DataVec.push_back(Segment.AsIoBuffer());
+ }
+
+ std::vector<const IoBuffer*> DataPtrs;
+
+ for (IoBuffer& Data : DataVec)
+ {
+ DataPtrs.push_back(&Data);
+ }
+
+ WriteFile(Path, DataPtrs.data(), DataPtrs.size());
+}
+
IoBuffer
FileContents::Flatten()
{
@@ -676,7 +715,13 @@ ReadFile(std::filesystem::path Path)
void* Handle;
#if ZEN_PLATFORM_WINDOWS
- windows::Handle FromFile(CreateFileW(Path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr));
+ windows::Handle FromFile(CreateFileW(Path.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr,
+ OPEN_EXISTING,
+ 0,
+ nullptr));
if (FromFile == INVALID_HANDLE_VALUE)
{
FromFile.Detach();
@@ -717,7 +762,13 @@ bool
ScanFile(std::filesystem::path Path, const uint64_t ChunkSize, std::function<void(const void* Data, size_t Size)>&& ProcessFunc)
{
#if ZEN_PLATFORM_WINDOWS
- windows::Handle FromFile(CreateFileW(Path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr));
+ windows::Handle FromFile(CreateFileW(Path.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr,
+ OPEN_EXISTING,
+ 0,
+ nullptr));
if (FromFile == INVALID_HANDLE_VALUE)
{
FromFile.Detach();
@@ -1047,6 +1098,8 @@ std::filesystem::path
GetRunningExecutablePath()
{
#if ZEN_PLATFORM_WINDOWS
+ // TODO: make this long path aware
+
TCHAR ExePath[MAX_PATH];
DWORD PathLength = GetModuleFileName(NULL, ExePath, ZEN_ARRAY_COUNT(ExePath));
diff --git a/src/zencore/include/zencore/compactbinary.h b/src/zencore/include/zencore/compactbinary.h
index b546f97aa..66e621a8a 100644
--- a/src/zencore/include/zencore/compactbinary.h
+++ b/src/zencore/include/zencore/compactbinary.h
@@ -5,6 +5,7 @@
#include <zencore/zencore.h>
#include <zencore/enumflags.h>
+#include <zencore/guid.h>
#include <zencore/intmath.h>
#include <zencore/iobuffer.h>
#include <zencore/iohash.h>
@@ -141,13 +142,6 @@ private:
uint64_t Ticks;
};
-struct Guid
-{
- uint32_t A, B, C, D;
-
- StringBuilderBase& ToString(StringBuilderBase& OutString) const;
-};
-
//////////////////////////////////////////////////////////////////////////
/**
@@ -891,6 +885,8 @@ public:
/** @see CbField::CbField */
using CbFieldView::CbFieldView;
+ using CbFieldView::TryGetSerializedView;
+
/** Construct an array with no fields. */
ZENCORE_API CbArrayView();
@@ -1410,6 +1406,10 @@ ZENCORE_API CbObject LoadCompactBinaryObject(const CompressedBuffer& Payload);
ZENCORE_API CbFieldIterator LoadCompactBinaryFromJson(std::string_view Json, std::string& Error);
ZENCORE_API CbFieldIterator LoadCompactBinaryFromJson(std::string_view Json);
+ZENCORE_API void SaveCompactBinary(BinaryWriter& Ar, const CbFieldView& Field);
+ZENCORE_API void SaveCompactBinary(BinaryWriter& Ar, const CbArrayView& Array);
+ZENCORE_API void SaveCompactBinary(BinaryWriter& Ar, const CbObjectView& Object);
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
diff --git a/src/zencore/include/zencore/compactbinarybuilder.h b/src/zencore/include/zencore/compactbinarybuilder.h
index 4be8c2ba5..53f00ae4e 100644
--- a/src/zencore/include/zencore/compactbinarybuilder.h
+++ b/src/zencore/include/zencore/compactbinarybuilder.h
@@ -46,7 +46,7 @@ class BinaryWriter;
*
* Example:
*
- * CbObjectRef WriteObject()
+ * CbObject WriteObject()
* {
* CbWriter<256> Writer;
* Writer.BeginObject();
@@ -60,7 +60,7 @@ class BinaryWriter;
* Writer.EndArray();
*
* Writer.EndObject();
- * return Writer.Save().AsObjectRef();
+ * return Writer.Save().AsObject();
* }
*/
class CbWriter
diff --git a/src/zencore/include/zencore/compactbinaryfile.h b/src/zencore/include/zencore/compactbinaryfile.h
new file mode 100644
index 000000000..00c37e941
--- /dev/null
+++ b/src/zencore/include/zencore/compactbinaryfile.h
@@ -0,0 +1,18 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zencore/compactbinary.h>
+#include <zencore/iohash.h>
+
+#include <filesystem>
+
+namespace zen {
+
+struct CbObjectFromFile
+{
+ CbObject Object;
+ IoHash Hash;
+};
+
+CbObjectFromFile LoadCompactBinaryObject(const std::filesystem::path& FilePath);
+
+} // namespace zen
diff --git a/src/zencore/include/zencore/filesystem.h b/src/zencore/include/zencore/filesystem.h
index 230d8d1c2..1a582672b 100644
--- a/src/zencore/include/zencore/filesystem.h
+++ b/src/zencore/include/zencore/filesystem.h
@@ -14,6 +14,7 @@
namespace zen {
class IoBuffer;
+class CompositeBuffer;
/** Delete directory (after deleting any contents)
*/
@@ -52,10 +53,19 @@ struct FileContents
};
ZENCORE_API FileContents ReadStdIn();
+
+/** Prepare file for reading
+
+ Note that this generally does not actually read the file contents. Instead it creates an
+ IoBuffer referencing the file contents so that it may be read at a later time. This is
+ leveraged to allow sending of data straight from disk cache and other optimizations.
+ */
ZENCORE_API FileContents ReadFile(std::filesystem::path Path);
+
ZENCORE_API bool ScanFile(std::filesystem::path Path, uint64_t ChunkSize, std::function<void(const void* Data, size_t Size)>&& ProcessFunc);
ZENCORE_API void WriteFile(std::filesystem::path Path, const IoBuffer* const* Data, size_t BufferCount);
ZENCORE_API void WriteFile(std::filesystem::path Path, IoBuffer Data);
+ZENCORE_API void WriteFile(std::filesystem::path Path, CompositeBuffer Data);
struct CopyFileOptions
{
diff --git a/src/zencore/include/zencore/fmtutils.h b/src/zencore/include/zencore/fmtutils.h
index 70867fe72..5c5169cd6 100644
--- a/src/zencore/include/zencore/fmtutils.h
+++ b/src/zencore/include/zencore/fmtutils.h
@@ -2,6 +2,7 @@
#pragma once
+#include <zencore/guid.h>
#include <zencore/iohash.h>
#include <zencore/string.h>
#include <zencore/uid.h>
@@ -23,7 +24,7 @@ struct fmt::formatter<zen::IoHash> : formatter<string_view>
{
zen::IoHash::String_t String;
Hash.ToHexString(String);
- return formatter<string_view>::format({String, zen::IoHash::StringLength}, ctx);
+ return fmt::formatter<string_view>::format({String, zen::IoHash::StringLength}, ctx);
}
};
@@ -35,7 +36,19 @@ struct fmt::formatter<zen::Oid> : formatter<string_view>
{
zen::StringBuilder<32> String;
Id.ToString(String);
- return formatter<string_view>::format({String.c_str(), zen::Oid::StringLength}, ctx);
+ return fmt::formatter<string_view>::format({String.c_str(), zen::Oid::StringLength}, ctx);
+ }
+};
+
+template<>
+struct fmt::formatter<zen::Guid> : formatter<string_view>
+{
+ template<typename FormatContext>
+ auto format(const zen::Guid& Id, FormatContext& ctx)
+ {
+ zen::StringBuilder<48> String;
+ Id.ToString(String);
+ return fmt::formatter<string_view>::format({String.c_str(), zen::Guid::StringLength}, ctx);
}
};
@@ -47,6 +60,6 @@ struct fmt::formatter<std::filesystem::path> : formatter<string_view>
{
zen::ExtendableStringBuilder<128> String;
String << Path.u8string();
- return formatter<string_view>::format(String.ToView(), ctx);
+ return fmt::formatter<string_view>::format(String.ToView(), ctx);
}
};
diff --git a/src/zencore/include/zencore/guid.h b/src/zencore/include/zencore/guid.h
new file mode 100644
index 000000000..751aa945f
--- /dev/null
+++ b/src/zencore/include/zencore/guid.h
@@ -0,0 +1,26 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/zencore.h>
+#include <compare>
+
+namespace zen {
+
+class StringBuilderBase;
+
+struct Guid
+{
+ uint32_t A, B, C, D;
+
+ static const int StringLength = 36;
+ typedef char String_t[StringLength + 1];
+
+ StringBuilderBase& ToString(StringBuilderBase& OutString) const;
+ static Guid FromString(std::string_view InString);
+
+ inline bool operator==(const Guid& Rhs) const = default;
+ inline auto operator<=>(const Guid& Rhs) const = default;
+};
+
+} // namespace zen
diff --git a/src/zencore/include/zencore/iobuffer.h b/src/zencore/include/zencore/iobuffer.h
index 2f248eb8b..bbc346f9b 100644
--- a/src/zencore/include/zencore/iobuffer.h
+++ b/src/zencore/include/zencore/iobuffer.h
@@ -414,6 +414,7 @@ public:
/** Make sure buffer data is memory resident, but avoid memory mapping data from files
*/
ZENCORE_API static IoBuffer ReadFromFileMaybe(IoBuffer& InBuffer);
+ inline static IoBuffer MakeFromMemory(MemoryView Memory) { return IoBuffer(IoBuffer::Wrap, Memory.GetData(), Memory.GetSize()); }
inline static IoBuffer MakeCloneFromMemory(const void* Ptr, size_t Sz)
{
if (Sz)
diff --git a/src/zencore/include/zencore/iohash.h b/src/zencore/include/zencore/iohash.h
index fd0f4b2a7..649a59c2c 100644
--- a/src/zencore/include/zencore/iohash.h
+++ b/src/zencore/include/zencore/iohash.h
@@ -42,6 +42,9 @@ struct IoHash
return Io;
}
+ // Temporary helper for transitioning APIs
+ static IoHash FromBLAKE3(const IoHash& Hash) { return Hash; }
+
static IoHash HashBuffer(const void* data, size_t byteCount);
static IoHash HashBuffer(MemoryView Data) { return HashBuffer(Data.GetData(), Data.GetSize()); }
static IoHash HashBuffer(const CompositeBuffer& Buffer);
diff --git a/src/zencore/include/zencore/string.h b/src/zencore/include/zencore/string.h
index ab111ff81..7a44bf781 100644
--- a/src/zencore/include/zencore/string.h
+++ b/src/zencore/include/zencore/string.h
@@ -306,6 +306,8 @@ public:
inline StringBuilderImpl& operator<<(const std::string_view str) { return AppendAscii(str); }
inline StringBuilderImpl& operator<<(const std::u8string_view str) { return AppendAscii(str); }
+ inline void EnsureNulTerminated() const { *m_CurPos = '\0'; }
+
protected:
inline void Init(C* Base, size_t Capacity)
{
@@ -313,8 +315,6 @@ protected:
m_End = Base + Capacity;
}
- inline void EnsureNulTerminated() const { *m_CurPos = '\0'; }
-
inline void EnsureCapacity(size_t ExtraRequired)
{
// precondition: we know the current buffer has enough capacity
@@ -607,14 +607,13 @@ ToHexNumber(UnsignedIntegral auto Value, char* OutString)
/// <summary>
/// Parse hex number string into a value, this formats the number in the correct order for a hexadecimal number
/// </summary>
-/// <param name="string">Input string</param>
-/// <param name="characterCount">Number of characters in string</param>
+/// <param name="HexString">Input string</param>
/// <param name="OutValue">Pointer to output value</param>
/// <returns>true if the input consisted of all valid hexadecimal characters</returns>
bool
-ParseHexNumber(const std::string HexString, UnsignedIntegral auto& OutValue)
+ParseHexNumber(const std::string_view HexString, UnsignedIntegral auto& OutValue)
{
- return ParseHexNumber(HexString.c_str(), sizeof(OutValue) * 2, (uint8_t*)&OutValue);
+ return ParseHexNumber(HexString.data(), sizeof(OutValue) * 2, (uint8_t*)&OutValue);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/src/zencore/include/zencore/system.h b/src/zencore/include/zencore/system.h
new file mode 100644
index 000000000..23665fb09
--- /dev/null
+++ b/src/zencore/include/zencore/system.h
@@ -0,0 +1,37 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/zencore.h>
+
+#include <string>
+
+namespace zen {
+
+class CbWriter;
+
+std::string GetMachineName();
+std::string_view GetOperatingSystemName();
+std::string_view GetCpuName();
+
+struct SystemMetrics
+{
+ int CpuCount = 1;
+ int CoreCount = 1;
+ int LogicalProcessorCount = 1;
+ uint64_t SystemMemoryMiB = 0;
+ uint64_t AvailSystemMemoryMiB = 0;
+ uint64_t VirtualMemoryMiB = 0;
+ uint64_t AvailVirtualMemoryMiB = 0;
+ uint64_t PageFileMiB = 0;
+ uint64_t AvailPageFileMiB = 0;
+};
+
+SystemMetrics GetSystemMetrics();
+
+void SetCpuCountForReporting(int FakeCpuCount);
+SystemMetrics GetSystemMetricsForReporting();
+
+void Describe(const SystemMetrics& Metrics, CbWriter& Writer);
+
+} // namespace zen
diff --git a/src/zencore/include/zencore/thread.h b/src/zencore/include/zencore/thread.h
index 9ff98de8c..9f2671610 100644
--- a/src/zencore/include/zencore/thread.h
+++ b/src/zencore/include/zencore/thread.h
@@ -107,6 +107,10 @@ public:
ZENCORE_API bool Wait(int TimeoutMs = -1);
ZENCORE_API void Close();
+#if ZEN_PLATFORM_WINDOWS
+ inline void* GetWindowsHandle() { return m_EventHandle; }
+#endif
+
protected:
explicit Event(void* EventHandle) : m_EventHandle(EventHandle) {}
@@ -181,6 +185,7 @@ public:
void AddCount(std::ptrdiff_t Count)
{
std::atomic_ptrdiff_t Old = Counter.fetch_add(Count);
+ ZEN_UNUSED(Old);
ZEN_ASSERT_SLOW(Old > 0);
}
diff --git a/src/zencore/include/zencore/uid.h b/src/zencore/include/zencore/uid.h
index a356da88d..4a1285416 100644
--- a/src/zencore/include/zencore/uid.h
+++ b/src/zencore/include/zencore/uid.h
@@ -60,7 +60,7 @@ struct Oid
const Oid& Generate();
[[nodiscard]] static Oid FromHexString(const std::string_view String);
StringBuilderBase& ToString(StringBuilderBase& OutString) const;
- void ToString(char OutString[StringLength]);
+ void ToString(char OutString[StringLength]) const;
[[nodiscard]] static Oid FromMemory(const void* Ptr);
auto operator<=>(const Oid& rhs) const = default;
diff --git a/src/zencore/include/zencore/zencore.h b/src/zencore/include/zencore/zencore.h
index 47ff2ebc2..71bd08e69 100644
--- a/src/zencore/include/zencore/zencore.h
+++ b/src/zencore/include/zencore/zencore.h
@@ -22,12 +22,15 @@
#ifdef _WIN32
# undef ZEN_PLATFORM_WINDOWS
# define ZEN_PLATFORM_WINDOWS 1
+# define ZEN_PLATFORM_NAME "Windows"
#elif defined(__linux__)
# undef ZEN_PLATFORM_LINUX
# define ZEN_PLATFORM_LINUX 1
+# define ZEN_PLATFORM_NAME "Linux"
#elif defined(__APPLE__)
# undef ZEN_PLATFORM_MAC
-# define ZEN_PLATFORM_MAC 1
+# define ZEN_PLATFORM_MAC 1
+# define ZEN_PLATFORM_NAME "MacOS"
#endif
#if ZEN_PLATFORM_WINDOWS
@@ -201,9 +204,11 @@ concept ContiguousRange = true;
#ifdef NDEBUG
# define ZEN_BUILD_DEBUG 0
# define ZEN_BUILD_RELEASE 1
+# define ZEN_BUILD_NAME "release"
#else
# define ZEN_BUILD_DEBUG 1
# define ZEN_BUILD_RELEASE 0
+# define ZEN_BUILD_NAME "debug"
#endif
//////////////////////////////////////////////////////////////////////////
@@ -323,7 +328,7 @@ char (&ZenArrayCountHelper(const T (&)[N]))[N + 1];
#if ZEN_PLATFORM_WINDOWS
# define ZEN_EXE_SUFFIX_LITERAL ".exe"
#else
-# define ZEN_EXE_SUFFIX_LITERAL
+# define ZEN_EXE_SUFFIX_LITERAL ""
#endif
#define ZEN_UNUSED(...) ((void)__VA_ARGS__)
diff --git a/src/zencore/session.cpp b/src/zencore/session.cpp
index ce4bfae1b..50c47c628 100644
--- a/src/zencore/session.cpp
+++ b/src/zencore/session.cpp
@@ -9,7 +9,7 @@
namespace zen {
static Oid GlobalSessionId;
-static char GlobalSessionString[Oid::StringLength];
+static Oid::String_t GlobalSessionString;
static std::once_flag SessionInitFlag;
Oid
@@ -32,4 +32,4 @@ GetSessionIdString()
return std::string_view(GlobalSessionString, Oid::StringLength);
}
-} // namespace zen \ No newline at end of file
+} // namespace zen
diff --git a/src/zencore/system.cpp b/src/zencore/system.cpp
new file mode 100644
index 000000000..f51273e0d
--- /dev/null
+++ b/src/zencore/system.cpp
@@ -0,0 +1,199 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include "zencore/system.h"
+
+#include <zencore/compactbinarybuilder.h>
+#include <zencore/except.h>
+#include <zencore/string.h>
+
+#if ZEN_PLATFORM_WINDOWS
+# include <zencore/windows.h>
+
+ZEN_THIRD_PARTY_INCLUDES_START
+# include <iphlpapi.h>
+# include <winsock2.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+#elif ZEN_PLATFORM_LINUX
+# include <sys/utsname.h>
+#elif ZEN_PLATFORM_MAC
+# include <unistd.h>
+#endif
+
+namespace zen {
+
+using namespace std::literals;
+
+int g_FakeCpuCount = 0;
+
+void
+SetCpuCountForReporting(int FakeCpuCount)
+{
+ g_FakeCpuCount = FakeCpuCount;
+}
+
+#if ZEN_PLATFORM_WINDOWS
+std::string
+GetMachineName()
+{
+ WCHAR NameBuffer[256];
+ DWORD dwNameSize = 255;
+ BOOL Success = GetComputerNameW(NameBuffer, &dwNameSize);
+
+ if (Success)
+ {
+ return WideToUtf8(NameBuffer);
+ }
+
+ return {};
+}
+
+SystemMetrics
+GetSystemMetrics()
+{
+ SYSTEM_INFO SysInfo{};
+ GetSystemInfo(&SysInfo);
+
+ SystemMetrics Metrics;
+
+ Metrics.LogicalProcessorCount = SysInfo.dwNumberOfProcessors;
+
+ // Determine physical core count
+
+ DWORD BufferSize = 0;
+ BOOL Result = GetLogicalProcessorInformation(nullptr, &BufferSize);
+ if (int32_t Error = GetLastError(); Error != ERROR_INSUFFICIENT_BUFFER)
+ {
+ ThrowSystemError(Error, "Failed to get buffer size for logical processor information");
+ }
+
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)Memory::Alloc(BufferSize);
+
+ Result = GetLogicalProcessorInformation(Buffer, &BufferSize);
+ if (!Result)
+ {
+ Memory::Free(Buffer);
+ throw std::runtime_error("Failed to get logical processor information");
+ }
+
+ DWORD ProcessorPkgCount = 0;
+ DWORD ProcessorCoreCount = 0;
+ DWORD ByteOffset = 0;
+ while (ByteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= BufferSize)
+ {
+ const SYSTEM_LOGICAL_PROCESSOR_INFORMATION& Slpi = Buffer[ByteOffset / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)];
+ if (Slpi.Relationship == RelationProcessorCore)
+ {
+ ProcessorCoreCount++;
+ }
+ else if (Slpi.Relationship == RelationProcessorPackage)
+ {
+ ProcessorPkgCount++;
+ }
+ ByteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+ }
+
+ Metrics.CoreCount = ProcessorCoreCount;
+ Metrics.CpuCount = ProcessorPkgCount;
+
+ Memory::Free(Buffer);
+
+ // Query memory status
+
+ MEMORYSTATUSEX MemStatus{.dwLength = sizeof(MEMORYSTATUSEX)};
+ GlobalMemoryStatusEx(&MemStatus);
+
+ Metrics.SystemMemoryMiB = MemStatus.ullTotalPhys / 1024 / 1024;
+ Metrics.AvailSystemMemoryMiB = MemStatus.ullAvailPhys / 1024 / 1024;
+ Metrics.VirtualMemoryMiB = MemStatus.ullTotalVirtual / 1024 / 1024;
+ Metrics.AvailVirtualMemoryMiB = MemStatus.ullAvailVirtual / 1024 / 1024;
+ Metrics.PageFileMiB = MemStatus.ullTotalPageFile / 1024 / 1024;
+ Metrics.AvailPageFileMiB = MemStatus.ullAvailPageFile / 1024 / 1024;
+
+ return Metrics;
+}
+#elif ZEN_PLATFORM_LINUX
+std::string
+GetMachineName()
+{
+ static char Result[256] = "";
+ if (!Result[0])
+ {
+ struct utsname name;
+ const char* SysName = name.nodename;
+ if (uname(&name))
+ {
+ SysName = "Unix Computer";
+ }
+
+ strcpy(Result, SysName);
+ }
+ return Result;
+}
+
+SystemMetrics
+GetSystemMetrics()
+{
+ return {};
+}
+#elif ZEN_PLATFORM_MAC
+std::string
+GetMachineName()
+{
+ static char Result[256] = "";
+
+ if (!Result[0])
+ {
+ gethostname(Result, sizeof(Result));
+ }
+ return Result;
+}
+
+SystemMetrics
+GetSystemMetrics()
+{
+ return {};
+}
+#else
+# error "Unknown platform"
+#endif
+
+SystemMetrics
+GetSystemMetricsForReporting()
+{
+ SystemMetrics Sm = GetSystemMetrics();
+
+ if (g_FakeCpuCount)
+ {
+ Sm.CoreCount = g_FakeCpuCount;
+ Sm.LogicalProcessorCount = g_FakeCpuCount;
+ }
+
+ return Sm;
+}
+
+std::string_view
+GetOperatingSystemName()
+{
+ return ZEN_PLATFORM_NAME;
+}
+
+std::string_view
+GetCpuName()
+{
+#if ZEN_ARCH_X64
+ return "x64"sv;
+#elif ZEN_ARCH_ARM64
+ return "arm64"sv;
+#endif
+}
+
+void
+Describe(const SystemMetrics& Metrics, CbWriter& Writer)
+{
+ Writer << "cpu_count" << Metrics.CpuCount << "core_count" << Metrics.CoreCount << "lp_count" << Metrics.LogicalProcessorCount
+ << "total_memory_mb" << Metrics.SystemMemoryMiB << "avail_memory_mb" << Metrics.AvailSystemMemoryMiB << "total_virtual_mb"
+ << Metrics.VirtualMemoryMiB << "avail_virtual_mb" << Metrics.AvailVirtualMemoryMiB << "total_pagefile_mb" << Metrics.PageFileMiB
+ << "avail_pagefile_mb" << Metrics.AvailPageFileMiB;
+}
+
+} // namespace zen
diff --git a/src/zencore/testing.cpp b/src/zencore/testing.cpp
index 5531aa738..6e1f55eda 100644
--- a/src/zencore/testing.cpp
+++ b/src/zencore/testing.cpp
@@ -34,6 +34,10 @@ TestRunner::ApplyCommandLine(int argc, char const* const* argv)
{
spdlog::set_level(spdlog::level::debug);
}
+ else if (argv[i] == "--verbose"sv)
+ {
+ spdlog::set_level(spdlog::level::trace);
+ }
}
return 0;
@@ -42,11 +46,9 @@ TestRunner::ApplyCommandLine(int argc, char const* const* argv)
int
TestRunner::Run()
{
- int Rv = m_Impl->Session.run();
-
- return Rv;
+ return m_Impl->Session.run();
}
} // namespace zen::testing
-#endif
+#endif // ZEN_WITH_TESTS
diff --git a/src/zencore/thread.cpp b/src/zencore/thread.cpp
index a44c0ee90..b225c8aff 100644
--- a/src/zencore/thread.cpp
+++ b/src/zencore/thread.cpp
@@ -18,6 +18,8 @@
# include <shellapi.h>
# include <Shlobj.h>
# include <zencore/windows.h>
+# pragma comment(lib, "shell32.lib")
+# pragma comment(lib, "user32.lib")
#else
# include <chrono>
# include <condition_variable>
diff --git a/src/zencore/uid.cpp b/src/zencore/uid.cpp
index 86cdfae3a..0f04d70ac 100644
--- a/src/zencore/uid.cpp
+++ b/src/zencore/uid.cpp
@@ -91,9 +91,10 @@ Oid::FromMemory(const void* Ptr)
}
void
-Oid::ToString(char OutString[StringLength])
+Oid::ToString(char OutString[StringLength]) const
{
ToHexBytes(reinterpret_cast<const uint8_t*>(OidBits), sizeof(Oid::OidBits), OutString);
+ OutString[StringLength] = '\0';
}
StringBuilderBase&
diff --git a/src/zencore/xmake.lua b/src/zencore/xmake.lua
index ef68b4c3c..706adff81 100644
--- a/src/zencore/xmake.lua
+++ b/src/zencore/xmake.lua
@@ -2,6 +2,7 @@
target('zencore')
set_kind("static")
+ set_group("libs")
add_headerfiles("**.h")
add_configfiles("include/zencore/config.h.in")
on_load(function (target)