GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 57 / 1 / 58
Functions: 100.0% 9 / 0 / 9
Branches: 57.7% 45 / 0 / 78

src/util/CommonUtil.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "CommonUtil.h"
4
5 #include <SourceFile.h> // Must be included before windows.h due to symbol name ambiguities
6
7 #include <cxxabi.h>
8
9 namespace spice::compiler {
10
11 /**
12 * Search all occurrences of needle in haystack and replace them with the replacement
13 *
14 * @param haystack Input string
15 * @param needle String to search
16 * @param replacement String to replace
17 */
18 3061993 void CommonUtil::replaceAll(std::string &haystack, const std::string &needle, const std::string &replacement) {
19 3061993 size_t start_pos = 0;
20
2/2
✓ Branch 8 → 3 taken 24681 times.
✓ Branch 8 → 9 taken 3061993 times.
3086674 while ((start_pos = haystack.find(needle, start_pos)) != std::string::npos) {
21 24681 haystack.replace(start_pos, needle.length(), replacement);
22 24681 start_pos += replacement.length();
23 }
24 3061993 }
25
26 /**
27 * Split the given haystack by the needle and return the last fragment
28 *
29 * @param haystack Input string
30 * @param needle String to search
31 * @return Last fragment
32 */
33 96071 std::string CommonUtil::getLastFragment(const std::string &haystack, const std::string &needle) {
34 96071 const size_t index = haystack.rfind(needle);
35
2/2
✓ Branch 3 → 4 taken 96068 times.
✓ Branch 3 → 5 taken 3 times.
96071 return index == std::string::npos ? haystack : haystack.substr(index + needle.length());
36 }
37
38 /**
39 * Trim the given input string
40 *
41 * @param input Input string
42 * @return Trimmed string
43 */
44 749 std::string CommonUtil::trim(const std::string &input) {
45 749 const size_t first = input.find_first_not_of(' ');
46
2/2
✓ Branch 3 → 4 taken 6 times.
✓ Branch 3 → 5 taken 743 times.
749 if (first == std::string::npos)
47 6 return input;
48 743 const size_t last = input.find_last_not_of(' ');
49 743 const size_t newLength = last - first + 1;
50 743 return input.substr(first, newLength);
51 }
52
53 /**
54 * Split the given input string by spaces
55 *
56 * @param input Input string
57 * @return Vector of fragments
58 */
59 30 std::vector<std::string> CommonUtil::split(const std::string &input) {
60 30 std::vector<std::string> result;
61
2/4
✓ Branch 2 → 3 taken 30 times.
✗ Branch 2 → 20 not taken.
✓ Branch 3 → 4 taken 30 times.
✗ Branch 3 → 18 not taken.
30 std::istringstream stream(trim(input));
62
63 30 std::string token;
64
4/6
✓ Branch 11 → 12 taken 103 times.
✗ Branch 11 → 24 not taken.
✓ Branch 12 → 13 taken 103 times.
✗ Branch 12 → 24 not taken.
✓ Branch 13 → 7 taken 73 times.
✓ Branch 13 → 14 taken 30 times.
103 while (std::getline(stream, token, ' '))
65
2/4
✓ Branch 7 → 8 taken 73 times.
✗ Branch 7 → 23 not taken.
✓ Branch 8 → 9 taken 73 times.
✗ Branch 8 → 21 not taken.
73 result.push_back(trim(token));
66
67 30 return result;
68 30 }
69
70 /**
71 * Return the given number of bytes in a human-readable format
72 *
73 * @return Human-readable size string
74 */
75 8 std::string CommonUtil::formatBytes(const size_t bytes) {
76 8 const char *units[] = {"B", "KB", "MB", "GB", "TB"};
77
78 8 auto size = static_cast<double>(bytes);
79 8 unsigned int unitIndex = 0;
80
3/4
✓ Branch 4 → 5 taken 15 times.
✓ Branch 4 → 6 taken 8 times.
✓ Branch 5 → 3 taken 15 times.
✗ Branch 5 → 6 not taken.
23 while (size >= 1024 && unitIndex < std::size(units) - 1) {
81 15 size /= 1024;
82 15 unitIndex++;
83 }
84
85 char buffer[20];
86 8 snprintf(buffer, sizeof(buffer), "%.2f %s", size, units[unitIndex]);
87
1/2
✓ Branch 8 → 9 taken 8 times.
✗ Branch 8 → 13 not taken.
16 return {buffer};
88 }
89
90 /**
91 * Demangle CXX type name
92 *
93 * @param mangledName Mangled CXX type name
94 * @return Demangled name
95 */
96 1310526 std::string CommonUtil::demangleTypeName(const char *mangledName) {
97 int status;
98
1/2
✓ Branch 2 → 3 taken 1310526 times.
✗ Branch 2 → 25 not taken.
1310526 char *demangled = abi::__cxa_demangle(mangledName, nullptr, nullptr, &status);
99
2/2
✓ Branch 3 → 4 taken 1310525 times.
✓ Branch 3 → 12 taken 1 time.
1310526 if (status == 0) {
100
1/2
✓ Branch 6 → 7 taken 1310525 times.
✗ Branch 6 → 19 not taken.
1310525 std::string result(demangled);
101 1310525 free(demangled);
102
1/2
✓ Branch 8 → 9 taken 1310525 times.
✗ Branch 8 → 10 not taken.
1310525 return result;
103 } // LCOV_EXCL_LINE - False positive
104
1/2
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 22 not taken.
1 return mangledName;
105 }
106
107 /**
108 * Check if the given string is a valid, mangled name
109 *
110 * @return Valid mangled name or not
111 */
112 106439 bool CommonUtil::isValidMangledName(const std::string &mangledName) {
113 int status;
114
1/2
✓ Branch 3 → 4 taken 106439 times.
✗ Branch 3 → 6 not taken.
106439 char *demangled = abi::__cxa_demangle(mangledName.c_str(), nullptr, nullptr, &status);
115 106439 free(demangled);
116 106439 return status == 0;
117 }
118
119 /**
120 * Obtain current year
121 *
122 * @return Current year
123 */
124 1147 int CommonUtil::getCurrentYear() {
125 1147 const std::time_t t = std::time(nullptr);
126 1147 const std::tm *tm = std::localtime(&t);
127 1147 return tm->tm_year + 1900;
128 }
129
130 /**
131 * Generate the version info string for the Spice driver
132 *
133 * @return Version info string
134 */
135 574 std::string CommonUtil::buildVersionInfo() {
136
1/2
✓ Branch 2 → 3 taken 574 times.
✗ Branch 2 → 29 not taken.
574 std::stringstream versionString;
137
7/14
✓ Branch 3 → 4 taken 574 times.
✗ Branch 3 → 27 not taken.
✓ Branch 4 → 5 taken 574 times.
✗ Branch 4 → 27 not taken.
✓ Branch 5 → 6 taken 574 times.
✗ Branch 5 → 27 not taken.
✓ Branch 6 → 7 taken 574 times.
✗ Branch 6 → 27 not taken.
✓ Branch 7 → 8 taken 574 times.
✗ Branch 7 → 27 not taken.
✓ Branch 8 → 9 taken 574 times.
✗ Branch 8 → 27 not taken.
✓ Branch 9 → 10 taken 574 times.
✗ Branch 9 → 27 not taken.
574 versionString << "Spice version: " << SPICE_VERSION << " " << SPICE_TARGET_OS << "/" << SPICE_TARGET_ARCH << "\n";
138
3/6
✓ Branch 10 → 11 taken 574 times.
✗ Branch 10 → 27 not taken.
✓ Branch 11 → 12 taken 574 times.
✗ Branch 11 → 27 not taken.
✓ Branch 12 → 13 taken 574 times.
✗ Branch 12 → 27 not taken.
574 versionString << "Git hash: " << SPICE_GIT_HASH << "\n";
139
3/6
✓ Branch 13 → 14 taken 574 times.
✗ Branch 13 → 27 not taken.
✓ Branch 14 → 15 taken 574 times.
✗ Branch 14 → 27 not taken.
✓ Branch 15 → 16 taken 574 times.
✗ Branch 15 → 27 not taken.
574 versionString << "LLVM version: " << LLVM_VERSION_STRING << "\n";
140
3/6
✓ Branch 16 → 17 taken 574 times.
✗ Branch 16 → 27 not taken.
✓ Branch 17 → 18 taken 574 times.
✗ Branch 17 → 27 not taken.
✓ Branch 18 → 19 taken 574 times.
✗ Branch 18 → 27 not taken.
574 versionString << "built by: " << SPICE_BUILT_BY << "\n\n";
141
2/4
✓ Branch 19 → 20 taken 574 times.
✗ Branch 19 → 27 not taken.
✓ Branch 21 → 22 taken 574 times.
✗ Branch 21 → 27 not taken.
574 versionString << "(c) Marc Auberer 2021-" << getCurrentYear();
142
1/2
✓ Branch 22 → 23 taken 574 times.
✗ Branch 22 → 27 not taken.
1148 return versionString.str();
143 574 }
144
145 } // namespace spice::compiler
146