From 51ec3b9687ba4cc74d3d39a4bc5bdc0f93d59463 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 22 Jun 2025 12:36:08 +0200 Subject: [PATCH 1/6] replace PPC_FUNC_NAME with `ppc::util::FuncName()` implementation --- modules/core/task/include/task.hpp | 12 ++++----- modules/core/util/include/util.hpp | 43 ++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/modules/core/task/include/task.hpp b/modules/core/task/include/task.hpp index 8223878d..5b73dc70 100644 --- a/modules/core/task/include/task.hpp +++ b/modules/core/task/include/task.hpp @@ -108,16 +108,16 @@ class Task { /// @brief Validates input data and task attributes before execution. /// @return True if validation is successful. virtual bool Validation() final { - InternalOrderTest(PPC_FUNC_NAME); + InternalOrderTest(ppc::util::FuncName()); return ValidationImpl(); } /// @brief Performs preprocessing on the input data. /// @return True if preprocessing is successful. virtual bool PreProcessing() final { - InternalOrderTest(PPC_FUNC_NAME); + InternalOrderTest(ppc::util::FuncName()); if (state_of_testing_ == StateOfTesting::kFunc) { - InternalTimeTest(PPC_FUNC_NAME); + InternalTimeTest(ppc::util::FuncName()); } return PreProcessingImpl(); } @@ -125,16 +125,16 @@ class Task { /// @brief Executes the main logic of the task. /// @return True if execution is successful. virtual bool Run() final { - InternalOrderTest(PPC_FUNC_NAME); + InternalOrderTest(ppc::util::FuncName()); return RunImpl(); } /// @brief Performs postprocessing on the output data. /// @return True if postprocessing is successful. virtual bool PostProcessing() final { - InternalOrderTest(PPC_FUNC_NAME); + InternalOrderTest(ppc::util::FuncName()); if (state_of_testing_ == StateOfTesting::kFunc) { - InternalTimeTest(PPC_FUNC_NAME); + InternalTimeTest(ppc::util::FuncName()); } return PostProcessingImpl(); } diff --git a/modules/core/util/include/util.hpp b/modules/core/util/include/util.hpp index a6fdea75..59c2f074 100644 --- a/modules/core/util/include/util.hpp +++ b/modules/core/util/include/util.hpp @@ -3,13 +3,12 @@ #include #include #include +#include #include #include #include "nlohmann/json_fwd.hpp" -#define PPC_FUNC_NAME __func__ - #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4459) @@ -27,6 +26,46 @@ using NlohmannJsonTypeError = nlohmann::json::type_error; namespace ppc::util { +/** + * @brief Extract the bare function name (e.g. "PreProcessing" or "foo") + * from a full signature provided by std::source_location, + * working both on GCC/Clang and MSVC. + * + * @param loc Source location (file, line, pretty-signature). + * Defaults to the call site via std::source_location::current(). + * @return A std::string containing only the function name. + * + * @note On GCC/Clang, loc.function_name() yields a “pretty” signature + * including namespaces, templates and parameter list. + * On MSVC, it also includes return type and calling convention. + * This function strips off everything before the last `::` (if any), + * and any parameter list or qualifiers after the name. + */ +inline std::string FuncName(const std::source_location& loc = std::source_location::current()) { + std::string_view full = loc.function_name(); + // 1) find end of name (just before '(' or end of string) + size_t paren = full.find('('); + size_t name_end = (paren == std::string_view::npos ? full.size() : paren); + + // 2) try to strip namespaces/classes via '::' + size_t colons = full.rfind("::", name_end); + size_t start = (colons == std::string_view::npos ? 0 : colons + 2); + + // 3) on MSVC there's often a return-type + "__cdecl " prefix before the name +#ifdef _MSC_VER + if (colons == std::string_view::npos) { + // if no '::', drop everything up to last space before name_end + size_t last_space = full.rfind(' ', name_end); + if (last_space != std::string_view::npos) { + start = last_space + 1; + } + } +#endif + + // 4) construct owning string of just the name + return std::string{full.substr(start, name_end - start)}; +} + enum GTestParamIndex : uint8_t { kTaskGetter, kNameTest, kTestParams }; std::string GetAbsoluteTaskPath(const std::string& id_path, const std::string& relative_path); From 686006e7913dee9d362d3e3675cb5f3eb588acae Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 22 Jun 2025 12:48:42 +0200 Subject: [PATCH 2/6] log function names in task lifecycle methods using `ppc::util::FuncName()` --- modules/core/task/include/task.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/core/task/include/task.hpp b/modules/core/task/include/task.hpp index 5b73dc70..b7fc37a2 100644 --- a/modules/core/task/include/task.hpp +++ b/modules/core/task/include/task.hpp @@ -108,6 +108,7 @@ class Task { /// @brief Validates input data and task attributes before execution. /// @return True if validation is successful. virtual bool Validation() final { + std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); return ValidationImpl(); } @@ -115,6 +116,7 @@ class Task { /// @brief Performs preprocessing on the input data. /// @return True if preprocessing is successful. virtual bool PreProcessing() final { + std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); if (state_of_testing_ == StateOfTesting::kFunc) { InternalTimeTest(ppc::util::FuncName()); @@ -125,6 +127,7 @@ class Task { /// @brief Executes the main logic of the task. /// @return True if execution is successful. virtual bool Run() final { + std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); return RunImpl(); } @@ -132,6 +135,7 @@ class Task { /// @brief Performs postprocessing on the output data. /// @return True if postprocessing is successful. virtual bool PostProcessing() final { + std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); if (state_of_testing_ == StateOfTesting::kFunc) { InternalTimeTest(ppc::util::FuncName()); From 94f5988945f5c8b1fbdb5be61f246f91bd5ea818 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 22 Jun 2025 13:02:07 +0200 Subject: [PATCH 3/6] remove unnecessary debug logs in task lifecycle methods and update macOS workflow with Xcode setup --- .github/workflows/mac.yml | 6 +++++- modules/core/task/include/task.hpp | 4 ---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 87b18454..ff6a27d7 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -3,11 +3,15 @@ on: jobs: macos-clang-build: - runs-on: macOS-latest + runs-on: macos-latest steps: - uses: actions/checkout@v4 with: submodules: recursive + - name: Install Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: 'latest' - name: Setup environment run: | brew update-reset diff --git a/modules/core/task/include/task.hpp b/modules/core/task/include/task.hpp index b7fc37a2..5b73dc70 100644 --- a/modules/core/task/include/task.hpp +++ b/modules/core/task/include/task.hpp @@ -108,7 +108,6 @@ class Task { /// @brief Validates input data and task attributes before execution. /// @return True if validation is successful. virtual bool Validation() final { - std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); return ValidationImpl(); } @@ -116,7 +115,6 @@ class Task { /// @brief Performs preprocessing on the input data. /// @return True if preprocessing is successful. virtual bool PreProcessing() final { - std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); if (state_of_testing_ == StateOfTesting::kFunc) { InternalTimeTest(ppc::util::FuncName()); @@ -127,7 +125,6 @@ class Task { /// @brief Executes the main logic of the task. /// @return True if execution is successful. virtual bool Run() final { - std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); return RunImpl(); } @@ -135,7 +132,6 @@ class Task { /// @brief Performs postprocessing on the output data. /// @return True if postprocessing is successful. virtual bool PostProcessing() final { - std::cout << ppc::util::FuncName() << '\n'; InternalOrderTest(ppc::util::FuncName()); if (state_of_testing_ == StateOfTesting::kFunc) { InternalTimeTest(ppc::util::FuncName()); From b33a506abac793bae4d66958abfe69fb36c6ee11 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 22 Jun 2025 13:06:03 +0200 Subject: [PATCH 4/6] add Xcode setup step to macOS GitHub workflows --- .github/workflows/mac.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index ff6a27d7..4899ca55 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -53,6 +53,10 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + - name: Install Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: 'latest' - name: Setup environment run: | brew update-reset @@ -94,6 +98,10 @@ jobs: runs-on: macOS-latest steps: - uses: actions/checkout@v4 + - name: Install Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: 'latest' - name: Setup environment run: | brew update-reset @@ -156,6 +164,10 @@ jobs: runs-on: macOS-latest steps: - uses: actions/checkout@v4 + - name: Install Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: 'latest' - name: Setup environment run: | brew update-reset From 11f586e8d813b9508164134a71b595329b59a544 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Sun, 22 Jun 2025 13:58:32 +0200 Subject: [PATCH 5/6] simplify `ppc::util::FuncName()` implementation and refine documentation --- modules/core/util/include/util.hpp | 49 +++++++++++------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/modules/core/util/include/util.hpp b/modules/core/util/include/util.hpp index 59c2f074..4ec5b242 100644 --- a/modules/core/util/include/util.hpp +++ b/modules/core/util/include/util.hpp @@ -27,43 +27,30 @@ using NlohmannJsonTypeError = nlohmann::json::type_error; namespace ppc::util { /** - * @brief Extract the bare function name (e.g. "PreProcessing" or "foo") - * from a full signature provided by std::source_location, - * working both on GCC/Clang and MSVC. + * @brief Obtain the simple function name (e.g. "PreProcessing" or "foo") + * from the full signature returned by std::source_location. * - * @param loc Source location (file, line, pretty-signature). + * @param loc Source location info (file, line, full signature). * Defaults to the call site via std::source_location::current(). - * @return A std::string containing only the function name. + * @return A std::string with only the function’s unqualified name. * - * @note On GCC/Clang, loc.function_name() yields a “pretty” signature - * including namespaces, templates and parameter list. - * On MSVC, it also includes return type and calling convention. - * This function strips off everything before the last `::` (if any), - * and any parameter list or qualifiers after the name. + * @details + * - On GCC/Clang, function_name() returns a pretty signature + * including namespaces, templates, and parameters. + * - On MSVC, it also includes return type and calling convention. + * - This routine removes any leading scope qualifiers (“::…”) and + * drops everything from the first '(' onward. */ -inline std::string FuncName(const std::source_location& loc = std::source_location::current()) { - std::string_view full = loc.function_name(); - // 1) find end of name (just before '(' or end of string) - size_t paren = full.find('('); - size_t name_end = (paren == std::string_view::npos ? full.size() : paren); - - // 2) try to strip namespaces/classes via '::' - size_t colons = full.rfind("::", name_end); - size_t start = (colons == std::string_view::npos ? 0 : colons + 2); - // 3) on MSVC there's often a return-type + "__cdecl " prefix before the name -#ifdef _MSC_VER - if (colons == std::string_view::npos) { - // if no '::', drop everything up to last space before name_end - size_t last_space = full.rfind(' ', name_end); - if (last_space != std::string_view::npos) { - start = last_space + 1; - } +inline std::string FuncName(const std::source_location& loc = std::source_location::current()) { + std::string s{loc.function_name()}; + if (auto p = s.find('('); p != std::string::npos) { + s.resize(p); // drop “(…)” } -#endif - - // 4) construct owning string of just the name - return std::string{full.substr(start, name_end - start)}; + if (auto p = s.rfind("::"); p != std::string::npos) { + s.erase(0, p + 2); // drop namespaces + } + return s; } enum GTestParamIndex : uint8_t { kTaskGetter, kNameTest, kTestParams }; From 462acd5abe7f2659d9d0485d94a85c71ceb7b8d3 Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Mon, 23 Jun 2025 23:12:46 +0200 Subject: [PATCH 6/6] refine `ppc::util::FuncName()` documentation for clarity and brevity --- modules/core/util/include/util.hpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/modules/core/util/include/util.hpp b/modules/core/util/include/util.hpp index 4ec5b242..9d48d5b0 100644 --- a/modules/core/util/include/util.hpp +++ b/modules/core/util/include/util.hpp @@ -27,21 +27,11 @@ using NlohmannJsonTypeError = nlohmann::json::type_error; namespace ppc::util { /** - * @brief Obtain the simple function name (e.g. "PreProcessing" or "foo") - * from the full signature returned by std::source_location. + * @brief Returns the unqualified name of the current function. * - * @param loc Source location info (file, line, full signature). - * Defaults to the call site via std::source_location::current(). - * @return A std::string with only the function’s unqualified name. - * - * @details - * - On GCC/Clang, function_name() returns a pretty signature - * including namespaces, templates, and parameters. - * - On MSVC, it also includes return type and calling convention. - * - This routine removes any leading scope qualifiers (“::…”) and - * drops everything from the first '(' onward. + * @param loc Source location, defaults to the current function. + * @return Function name without namespaces or parameters. */ - inline std::string FuncName(const std::source_location& loc = std::source_location::current()) { std::string s{loc.function_name()}; if (auto p = s.find('('); p != std::string::npos) {