Skip to content

Commit 02a0aeb

Browse files
authored
DPL: improve type_to_task_name function (#15006)
- Out of line and avoid usage of stringstream. - Remove non-sense abbreviations
1 parent dd70bca commit 02a0aeb

File tree

5 files changed

+147
-17
lines changed

5 files changed

+147
-17
lines changed

Framework/Core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ o2_add_library(Framework
1616
src/ArrowTableSlicingCache.cxx
1717
src/AnalysisDataModel.cxx
1818
src/AnalysisSupportHelpers.cxx
19+
src/AnalysisTask.cxx
1920
src/ASoA.cxx
2021
src/ASoAHelpers.cxx
2122
src/AsyncQueue.cxx
@@ -254,6 +255,7 @@ add_executable(o2-test-framework-core
254255
test/test_TimeParallelPipelining.cxx
255256
test/test_TimesliceIndex.cxx
256257
test/test_TypeTraits.cxx
258+
test/test_TypeToTaskName.cxx
257259
test/test_TopologyPolicies.cxx
258260
test/test_Variants.cxx
259261
test/test_WorkflowHelpers.cxx

Framework/Core/include/Framework/AnalysisTask.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737

3838
namespace o2::framework
3939
{
40+
/// Convert a CamelCase task struct name to snake-case task name
41+
std::string type_to_task_name(std::string_view const& camelCase);
42+
4043
/// A more familiar task API for the DPL analysis framework.
4144
/// This allows you to define your own tasks as subclasses
4245
/// of o2::framework::AnalysisTask and to pass them in the specification
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
#include <string>
12+
13+
namespace o2::framework
14+
{
15+
/// Convert a CamelCase task struct name to snake-case task name
16+
std::string type_to_task_name(std::string_view const& camelCase)
17+
{
18+
std::string result;
19+
result.reserve(camelCase.size() * 2 + 2);
20+
21+
// The first character is always -.
22+
result += "-";
23+
result += static_cast<char>(std::tolower(camelCase[0]));
24+
25+
for (auto it = camelCase.begin() + 1; it != camelCase.end(); ++it) {
26+
if (std::isupper(*it) && *(it - 1) != '-') {
27+
result += '-';
28+
}
29+
result += static_cast<char>(std::tolower(*it));
30+
}
31+
// Post-process to consolidate common ALICE abbreviations
32+
// Process backwards to handle patterns correctly
33+
static const struct {
34+
std::string_view pattern;
35+
std::string_view replacement;
36+
} abbreviations[] = {
37+
{"-h-m-p-i-d", "-hmpid"},
38+
{"-e-m-c-a-l", "-emcal"},
39+
{"-e-m-c", "-emc"},
40+
{"-i-t-s", "-its"},
41+
{"-t-p-c", "-tpc"},
42+
{"-q-c-d", "-qcd"},
43+
{"-t-o-f", "-tof"},
44+
{"-t-r-d", "-trd"},
45+
{"-f-v0", "-fv0"},
46+
{"-q-a", "-qa"},
47+
{"-b-c", "-bc"},
48+
{"-q-c", "-qc"}};
49+
50+
std::string consolidated;
51+
consolidated.reserve(result.size());
52+
53+
for (int i = result.size() - 1; i >= 0;) {
54+
bool matched = false;
55+
56+
for (const auto& abbr : abbreviations) {
57+
int startPos = i - abbr.pattern.size() + 1;
58+
if (startPos >= 0 && result.compare(startPos, abbr.pattern.size(), abbr.pattern.data()) == 0) {
59+
consolidated.insert(0, abbr.replacement);
60+
i = startPos - 1;
61+
matched = true;
62+
break;
63+
}
64+
}
65+
66+
if (!matched) {
67+
consolidated.insert(0, 1, result[i]);
68+
--i;
69+
}
70+
}
71+
if (consolidated[0] == '-') {
72+
return std::string(consolidated.data() + 1);
73+
}
74+
75+
return consolidated;
76+
}
77+
} // namespace o2::framework
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#include <catch_amalgamated.hpp>
13+
#include "Framework/AnalysisTask.h"
14+
#include <string_view>
15+
16+
using namespace o2::framework;
17+
18+
TEST_CASE("TypeIdHelpers_BasicConversion")
19+
{
20+
// Basic CamelCase to snake-case conversion
21+
REQUIRE((type_to_task_name(std::string_view("SimpleTask")) == "simple-task"));
22+
REQUIRE((type_to_task_name(std::string_view("MyTask")) == "my-task"));
23+
REQUIRE((type_to_task_name(std::string_view("Task")) == "task"));
24+
}
25+
26+
TEST_CASE("TypeIdHelpers_AbbreviationConsolidation")
27+
{
28+
// Test ALICE detector abbreviations
29+
REQUIRE(type_to_task_name(std::string_view("ITSQA")) == "its-qa");
30+
REQUIRE(type_to_task_name(std::string_view("TPCQCTask")) == "tpc-qc-task");
31+
REQUIRE(type_to_task_name(std::string_view("EMCALQATask")) == "emcal-qa-task");
32+
REQUIRE(type_to_task_name(std::string_view("HMPIDTask")) == "hmpid-task");
33+
REQUIRE(type_to_task_name(std::string_view("ITSTPCTask")) == "its-tpc-task");
34+
REQUIRE(type_to_task_name(std::string_view("QCFV0Task")) == "qc-fv0-task");
35+
}
36+
37+
TEST_CASE("TypeIdHelpers_QualityControlAbbreviations")
38+
{
39+
// Test quality control abbreviations
40+
REQUIRE(type_to_task_name(std::string_view("QATask")) == "qa-task");
41+
REQUIRE(type_to_task_name(std::string_view("QCTask")) == "qc-task");
42+
REQUIRE(type_to_task_name(std::string_view("QCDAnalysis")) == "qcd-analysis");
43+
}
44+
45+
TEST_CASE("TypeIdHelpers_ComplexNames")
46+
{
47+
// Test complex combinations
48+
REQUIRE(type_to_task_name(std::string_view("ITSQAAnalysisTask")) == "its-qa-analysis-task");
49+
REQUIRE(type_to_task_name(std::string_view("TPCEMCQCTask")) == "tpc-emc-qc-task");
50+
REQUIRE(type_to_task_name(std::string_view("MyITSTask")) == "my-its-task");
51+
}
52+
53+
TEST_CASE("TypeIdHelpers_EdgeCases")
54+
{
55+
// Single character
56+
REQUIRE(type_to_task_name(std::string_view("A")) == "a");
57+
58+
// All uppercase. BC is Bunch Crossing!
59+
//
60+
REQUIRE(type_to_task_name(std::string_view("ABC")) == "a-bc");
61+
REQUIRE(type_to_task_name(std::string_view("BC")) == "bc");
62+
63+
// Mixed with numbers (numbers are not uppercase, so no hyphens before them)
64+
REQUIRE(type_to_task_name(std::string_view("Task123")) == "task123");
65+
}

Framework/Foundation/include/Framework/TypeIdHelpers.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#define O2_FRAMEWORK_TYPEIDHELPERS_H_
1414

1515
#include <string_view>
16-
#include <sstream>
1716
#if __cplusplus >= 202002L
1817
#include <source_location>
1918
#endif
@@ -82,22 +81,6 @@ struct TypeIdHelpers {
8281
}
8382
};
8483

85-
/// Convert a CamelCase task struct name to snake-case task name
86-
inline static std::string type_to_task_name(std::string_view& camelCase)
87-
{
88-
std::ostringstream str;
89-
str << static_cast<char>(std::tolower(camelCase[0]));
90-
91-
for (auto it = camelCase.begin() + 1; it != camelCase.end(); ++it) {
92-
if (std::isupper(*it) && *(it - 1) != '-') {
93-
str << "-";
94-
}
95-
str << static_cast<char>(std::tolower(*it));
96-
}
97-
98-
return str.str();
99-
}
100-
10184
} // namespace o2::framework
10285

10386
#endif // O2_FRAMEWORK_TYPEIDHELPERS_H_

0 commit comments

Comments
 (0)