From ad0a18c945ace17bd8f8005adf2c410e22cd9193 Mon Sep 17 00:00:00 2001 From: dev0 Date: Sat, 29 Nov 2025 01:29:53 +0530 Subject: [PATCH] Utils --- Src/IACore/CMakeLists.txt | 1 + Src/IACore/imp/cpp/FileOps.cpp | 16 +++++ Src/IACore/imp/cpp/IACore.cpp | 50 +++++++++++++- Src/IACore/imp/cpp/Logger.cpp | 7 +- Src/IACore/imp/cpp/StringOps.cpp | 101 ++++++++++++++++++++++++++++ Src/IACore/inc/IACore/FileOps.hpp | 9 ++- Src/IACore/inc/IACore/IACore.hpp | 13 ++++ Src/IACore/inc/IACore/Logger.hpp | 10 +-- Src/IACore/inc/IACore/StringOps.hpp | 29 ++++++++ Tools/Builder/Build.py | 4 +- 10 files changed, 225 insertions(+), 15 deletions(-) create mode 100644 Src/IACore/imp/cpp/StringOps.cpp create mode 100644 Src/IACore/inc/IACore/StringOps.hpp diff --git a/Src/IACore/CMakeLists.txt b/Src/IACore/CMakeLists.txt index 57cf6dc..fa687b2 100644 --- a/Src/IACore/CMakeLists.txt +++ b/Src/IACore/CMakeLists.txt @@ -4,6 +4,7 @@ set(SRC_FILES "imp/cpp/FileOps.cpp" "imp/cpp/AsyncOps.cpp" "imp/cpp/SocketOps.cpp" + "imp/cpp/StringOps.cpp" "imp/cpp/ProcessOps.cpp" "imp/cpp/StreamReader.cpp" "imp/cpp/StreamWriter.cpp" diff --git a/Src/IACore/imp/cpp/FileOps.cpp b/Src/IACore/imp/cpp/FileOps.cpp index 8d32e4e..9abfded 100644 --- a/Src/IACore/imp/cpp/FileOps.cpp +++ b/Src/IACore/imp/cpp/FileOps.cpp @@ -179,4 +179,20 @@ namespace IACore fclose(f); return result; } + + FilePath FileOps::NormalizeExecutablePath(IN CONST FilePath &path) + { +#if IA_PLATFORM_WINDOWS + return path; +#elif IA_PLATFORM_UNIX + String result(path); + if (path.extension() == ".exe") + result.resize(result.size() - 4); + if (!path.is_absolute() && !path.string().starts_with("./")) + result = "./" + result; + return FilePath(result); +#else +# error "unreachable. previous checks must have stopped compilation beforehand .unsupported platform." +#endif + } } // namespace IACore \ No newline at end of file diff --git a/Src/IACore/imp/cpp/IACore.cpp b/Src/IACore/imp/cpp/IACore.cpp index 8989163..bd2edf8 100644 --- a/Src/IACore/imp/cpp/IACore.cpp +++ b/Src/IACore/imp/cpp/IACore.cpp @@ -15,10 +15,56 @@ // along with this program. If not, see . #include +#include #include namespace IACore { - -} \ No newline at end of file + HRTimePoint g_startTime{}; + std::thread::id g_mainThreadID{}; + + VOID Initialize() + { + g_mainThreadID = std::this_thread::get_id(); + g_startTime = HRClock::now(); + Logger::Initialize(); + } + + VOID Terminate() + { + Logger::Terminate(); + } + + UINT64 GetTicksCount() + { + return std::chrono::duration_cast(HRClock::now() - g_startTime).count(); + } + + FLOAT64 GetSecondsCount() + { + return (HRClock::now() - g_startTime).count(); + } + + UINT32 GetRandom(IN UINT32 seed) + { + srand(seed); + return (UINT32) GetRandom(0, UINT32_MAX); + } + + INT64 GetRandom(IN INT64 min, IN INT64 max) + { + const auto t = static_cast(rand()) / static_cast(RAND_MAX); + return min + (max - min) * t; + } + + VOID Sleep(IN UINT64 milliseconds) + { + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); + } + + BOOL IsMainThread() + { + return std::this_thread::get_id() == g_mainThreadID; + } +} // namespace IACore \ No newline at end of file diff --git a/Src/IACore/imp/cpp/Logger.cpp b/Src/IACore/imp/cpp/Logger.cpp index 8a2efe5..86c1550 100644 --- a/Src/IACore/imp/cpp/Logger.cpp +++ b/Src/IACore/imp/cpp/Logger.cpp @@ -15,17 +15,16 @@ // along with this program. If not, see . #include +#include #include namespace IACore { Logger::ELogLevel Logger::s_logLevel{Logger::ELogLevel::WARN}; - HRTimePoint Logger::s_startTime{}; std::ofstream Logger::s_logFile{}; VOID Logger::Initialize() { - s_startTime = HRClock::now(); } VOID Logger::Terminate() @@ -55,9 +54,7 @@ namespace IACore VOID Logger::LogInternal(IN PCCHAR prefix, IN PCCHAR tag, IN String &&msg) { - std::chrono::duration elapsed = HRClock::now() - s_startTime; - double timestamp = elapsed.count(); - const auto outLine = std::format("[{:>8.3f}]: [{}]: {}", timestamp, tag, msg); + const auto outLine = std::format("[{:>8.3f}]: [{}]: {}", GetSecondsCount(), tag, msg); std::cout << prefix << outLine << "\033[39m\n"; if (s_logFile) { diff --git a/Src/IACore/imp/cpp/StringOps.cpp b/Src/IACore/imp/cpp/StringOps.cpp new file mode 100644 index 0000000..6c9d0a3 --- /dev/null +++ b/Src/IACore/imp/cpp/StringOps.cpp @@ -0,0 +1,101 @@ +// IACore-OSS; The Core Library for All IA Open Source Projects +// Copyright (C) 2025 IAS (ias@iasoft.dev) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include + +namespace IACore +{ + CONST String BASE64_CHAR_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + String StringOps::EncodeBase64(IN Span data) + { + String result; + result.reserve(((data.size() + 2) / 3) * 4); + for (size_t i = 0; i < data.size(); i += 3) + { + uint32_t value = 0; + INT32 num_bytes = 0; + for (INT32 j = 0; j < 3 && (i + j) < data.size(); ++j) + { + value = (value << 8) | data[i + j]; + num_bytes++; + } + for (INT32 j = 0; j < num_bytes + 1; ++j) + { + if (j < 4) + { + result += BASE64_CHAR_TABLE[(value >> (6 * (3 - j))) & 0x3F]; + } + } + if (num_bytes < 3) + { + for (INT32 j = 0; j < (3 - num_bytes); ++j) + { + result += '='; + } + } + } + return result; + } + + Vector StringOps::DecodeBase64(IN CONST String &data) + { + Vector result; + + CONST AUTO isBase64 = [](UINT8 c) { return (isalnum(c) || (c == '+') || (c == '/')); }; + + INT32 in_len = data.size(); + INT32 i = 0, j = 0, in_ = 0; + UINT8 tmpBuf0[4], tmpBuf1[3]; + + while (in_len-- && (data[in_] != '=') && isBase64(data[in_])) + { + tmpBuf0[i++] = data[in_]; + in_++; + if (i == 4) + { + for (i = 0; i < 4; i++) + tmpBuf0[i] = BASE64_CHAR_TABLE.find(tmpBuf0[i]); + + tmpBuf1[0] = (tmpBuf0[0] << 2) + ((tmpBuf0[1] & 0x30) >> 4); + tmpBuf1[1] = ((tmpBuf0[1] & 0xf) << 4) + ((tmpBuf0[2] & 0x3c) >> 2); + tmpBuf1[2] = ((tmpBuf0[2] & 0x3) << 6) + tmpBuf0[3]; + + for (i = 0; (i < 3); i++) + result.push_back(tmpBuf1[i]); + i = 0; + } + } + + if (i) + { + for (j = i; j < 4; j++) + tmpBuf0[j] = 0; + + for (j = 0; j < 4; j++) + tmpBuf0[j] = BASE64_CHAR_TABLE.find(tmpBuf0[j]); + + tmpBuf1[0] = (tmpBuf0[0] << 2) + ((tmpBuf0[1] & 0x30) >> 4); + tmpBuf1[1] = ((tmpBuf0[1] & 0xf) << 4) + ((tmpBuf0[2] & 0x3c) >> 2); + tmpBuf1[2] = ((tmpBuf0[2] & 0x3) << 6) + tmpBuf0[3]; + + for (j = 0; (j < i - 1); j++) + result.push_back(tmpBuf1[j]); + } + + return result; + } +} // namespace IACore \ No newline at end of file diff --git a/Src/IACore/inc/IACore/FileOps.hpp b/Src/IACore/inc/IACore/FileOps.hpp index bc78904..e3d5960 100644 --- a/Src/IACore/inc/IACore/FileOps.hpp +++ b/Src/IACore/inc/IACore/FileOps.hpp @@ -23,6 +23,9 @@ namespace IACore { class FileOps { + public: + STATIC FilePath NormalizeExecutablePath(IN CONST FilePath &path); + public: STATIC VOID UnmapFile(IN PCUINT8 mappedPtr); STATIC Expected MapFile(IN CONST FilePath &path, OUT SIZE_T &size); @@ -32,8 +35,10 @@ namespace IACore STATIC Expected ReadTextFile(IN CONST FilePath &path); STATIC Expected, String> ReadBinaryFile(IN CONST FilePath &path); - STATIC Expected WriteTextFile(IN CONST FilePath &path, IN CONST String &contents, IN BOOL overwrite = false); - STATIC Expected WriteBinaryFile(IN CONST FilePath &path, IN Span contents, IN BOOL overwrite = false); + STATIC Expected WriteTextFile(IN CONST FilePath &path, IN CONST String &contents, + IN BOOL overwrite = false); + STATIC Expected WriteBinaryFile(IN CONST FilePath &path, IN Span contents, + IN BOOL overwrite = false); private: STATIC UnorderedMap> s_mappedFiles; diff --git a/Src/IACore/inc/IACore/IACore.hpp b/Src/IACore/inc/IACore/IACore.hpp index 79f19f1..607365c 100644 --- a/Src/IACore/inc/IACore/IACore.hpp +++ b/Src/IACore/inc/IACore/IACore.hpp @@ -22,6 +22,19 @@ namespace IACore { + // Must be called from main thread + VOID Initialize(); + // Must be called from same thread as Initialize + VOID Terminate(); + + UINT64 GetTicksCount(); + FLOAT64 GetSecondsCount(); + + UINT32 GetRandom(IN UINT32 seed); + INT64 GetRandom(IN INT64 min, IN INT64 max); + + BOOL IsMainThread(); + VOID Sleep(IN UINT64 milliseconds); } // namespace IACore #endif diff --git a/Src/IACore/inc/IACore/Logger.hpp b/Src/IACore/inc/IACore/Logger.hpp index 8d60487..cb5bd3d 100644 --- a/Src/IACore/inc/IACore/Logger.hpp +++ b/Src/IACore/inc/IACore/Logger.hpp @@ -32,9 +32,6 @@ namespace IACore }; public: - STATIC VOID Initialize(); - STATIC VOID Terminate(); - STATIC BOOL EnableLoggingToDisk(IN PCCHAR filePath); STATIC VOID SetLogLevel(IN ELogLevel logLevel); @@ -109,7 +106,12 @@ namespace IACore private: STATIC ELogLevel s_logLevel; - STATIC HRTimePoint s_startTime; STATIC std::ofstream s_logFile; + + STATIC VOID Initialize(); + STATIC VOID Terminate(); + + friend VOID Initialize(); + friend VOID Terminate(); }; } \ No newline at end of file diff --git a/Src/IACore/inc/IACore/StringOps.hpp b/Src/IACore/inc/IACore/StringOps.hpp new file mode 100644 index 0000000..b0f6a18 --- /dev/null +++ b/Src/IACore/inc/IACore/StringOps.hpp @@ -0,0 +1,29 @@ +// IACore-OSS; The Core Library for All IA Open Source Projects +// Copyright (C) 2025 IAS (ias@iasoft.dev) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include + +namespace IACore +{ + class StringOps + { + public: + STATIC String EncodeBase64(IN Span data); + STATIC Vector DecodeBase64(IN CONST String& data); + }; +} \ No newline at end of file diff --git a/Tools/Builder/Build.py b/Tools/Builder/Build.py index 3b39396..ced6493 100644 --- a/Tools/Builder/Build.py +++ b/Tools/Builder/Build.py @@ -20,7 +20,7 @@ import os import sys def main(args: list[str]): - os.system("cmake -S. -B./Build/Linux -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug") - os.system("cmake --build ./Build/Linux") + os.system("cmake -S. -B./Build -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug") + os.system("cmake --build ./Build") main(sys.argv)