GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 98.6% 68 / 0 / 69
Functions: 100.0% 10 / 0 / 10
Branches: 58.0% 58 / 0 / 100

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 1187303 void CommonUtil::replaceAll(std::string &haystack, const std::string &needle, const std::string &replacement) {
19 1187303 size_t start_pos = 0;
20
2/2
✓ Branch 8 → 3 taken 7219 times.
✓ Branch 8 → 9 taken 1187303 times.
1194522 while ((start_pos = haystack.find(needle, start_pos)) != std::string::npos) {
21 7219 haystack.replace(start_pos, needle.length(), replacement);
22 7219 start_pos += replacement.length();
23 }
24 1187303 }
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 27081 std::string CommonUtil::getLastFragment(const std::string &haystack, const std::string &needle) {
34 27081 const size_t index = haystack.rfind(needle);
35
2/2
✓ Branch 3 → 4 taken 27078 times.
✓ Branch 3 → 5 taken 3 times.
27081 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 552 std::string CommonUtil::trim(const std::string &input) {
45 552 const size_t first = input.find_first_not_of(' ');
46
2/2
✓ Branch 3 → 4 taken 6 times.
✓ Branch 3 → 5 taken 546 times.
552 if (first == std::string::npos)
47 6 return input;
48 546 const size_t last = input.find_last_not_of(' ');
49 546 const size_t newLength = last - first + 1;
50 546 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 24 std::vector<std::string> CommonUtil::split(const std::string &input) {
60 24 std::vector<std::string> result;
61
2/4
✓ Branch 2 → 3 taken 24 times.
✗ Branch 2 → 20 not taken.
✓ Branch 3 → 4 taken 24 times.
✗ Branch 3 → 18 not taken.
24 std::istringstream stream(trim(input));
62
63 24 std::string token;
64
4/6
✓ Branch 11 → 12 taken 63 times.
✗ Branch 11 → 24 not taken.
✓ Branch 12 → 13 taken 63 times.
✗ Branch 12 → 24 not taken.
✓ Branch 13 → 7 taken 39 times.
✓ Branch 13 → 14 taken 24 times.
63 while (std::getline(stream, token, ' '))
65
2/4
✓ Branch 7 → 8 taken 39 times.
✗ Branch 7 → 23 not taken.
✓ Branch 8 → 9 taken 39 times.
✗ Branch 8 → 21 not taken.
39 result.push_back(trim(token));
66
67 24 return result;
68 24 }
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
5/6
✓ Branch 4 → 5 taken 15 times.
✓ Branch 4 → 9 taken 8 times.
✓ Branch 7 → 8 taken 15 times.
✗ Branch 7 → 9 not taken.
✓ Branch 10 → 3 taken 15 times.
✓ Branch 10 → 11 taken 8 times.
38 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 13 → 14 taken 8 times.
✗ Branch 13 → 17 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 1607075 std::string CommonUtil::demangleTypeName(const char *mangledName) {
97 int status;
98
1/2
✓ Branch 2 → 3 taken 1607075 times.
✗ Branch 2 → 25 not taken.
1607075 char *demangled = abi::__cxa_demangle(mangledName, nullptr, nullptr, &status);
99
2/2
✓ Branch 3 → 4 taken 1607074 times.
✓ Branch 3 → 11 taken 1 time.
1607075 if (status == 0) {
100
1/2
✓ Branch 6 → 7 taken 1607074 times.
✗ Branch 6 → 19 not taken.
1607074 std::string result(demangled);
101 1607074 free(demangled);
102
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1607074 times.
1607074 return result;
103 }
104
1/2
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 22 not taken.
2 return mangledName;
105 }
106
107 /**
108 * Check if the given string is a valid, mangled name
109 *
110 * @return
111 */
112 31337 bool CommonUtil::isValidMangledName(const std::string &mangledName) {
113 int status;
114
1/2
✓ Branch 3 → 4 taken 31337 times.
✗ Branch 3 → 6 not taken.
31337 char *demangled = abi::__cxa_demangle(mangledName.c_str(), nullptr, nullptr, &status);
115 31337 free(demangled);
116 31337 return status == 0;
117 }
118
119 /**
120 * Generate a circular import message from the given source files
121 *
122 * @param sourceFiles Source files that form the circular dependency chain
123 * @return Error message
124 */
125 1 std::string CommonUtil::getCircularImportMessage(std::stack<const SourceFile *> &sourceFiles) {
126
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 22 not taken.
1 std::stringstream message;
127
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 20 not taken.
1 message << "*-----*\n";
128
1/2
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 20 not taken.
1 message << "| |\n";
129
2/2
✓ Branch 13 → 6 taken 3 times.
✓ Branch 13 → 14 taken 1 time.
4 while (!sourceFiles.empty()) {
130
3/6
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 20 not taken.
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 20 not taken.
✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 20 not taken.
3 message << "| " << sourceFiles.top()->fileName << "\n";
131
1/2
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 20 not taken.
3 message << "| |\n";
132 3 sourceFiles.pop();
133 }
134
1/2
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 20 not taken.
1 message << "*-----*";
135
1/2
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 20 not taken.
2 return message.str();
136 1 }
137
138 909 int CommonUtil::getCurrentYear() {
139 909 const std::time_t t = std::time(nullptr);
140 909 const std::tm *tm = std::localtime(&t);
141 909 return tm->tm_year + 1900;
142 }
143
144 /**
145 * Generate the version info string for the Spice driver
146 *
147 * @return Version info string
148 */
149 455 std::string CommonUtil::buildVersionInfo() {
150
1/2
✓ Branch 2 → 3 taken 455 times.
✗ Branch 2 → 29 not taken.
455 std::stringstream versionString;
151
7/14
✓ Branch 3 → 4 taken 455 times.
✗ Branch 3 → 27 not taken.
✓ Branch 4 → 5 taken 455 times.
✗ Branch 4 → 27 not taken.
✓ Branch 5 → 6 taken 455 times.
✗ Branch 5 → 27 not taken.
✓ Branch 6 → 7 taken 455 times.
✗ Branch 6 → 27 not taken.
✓ Branch 7 → 8 taken 455 times.
✗ Branch 7 → 27 not taken.
✓ Branch 8 → 9 taken 455 times.
✗ Branch 8 → 27 not taken.
✓ Branch 9 → 10 taken 455 times.
✗ Branch 9 → 27 not taken.
455 versionString << "Spice version: " << SPICE_VERSION << " " << SPICE_TARGET_OS << "/" << SPICE_TARGET_ARCH << "\n";
152
3/6
✓ Branch 10 → 11 taken 455 times.
✗ Branch 10 → 27 not taken.
✓ Branch 11 → 12 taken 455 times.
✗ Branch 11 → 27 not taken.
✓ Branch 12 → 13 taken 455 times.
✗ Branch 12 → 27 not taken.
455 versionString << "Git hash: " << SPICE_GIT_HASH << "\n";
153
3/6
✓ Branch 13 → 14 taken 455 times.
✗ Branch 13 → 27 not taken.
✓ Branch 14 → 15 taken 455 times.
✗ Branch 14 → 27 not taken.
✓ Branch 15 → 16 taken 455 times.
✗ Branch 15 → 27 not taken.
455 versionString << "LLVM version: " << LLVM_VERSION_STRING << "\n";
154
3/6
✓ Branch 16 → 17 taken 455 times.
✗ Branch 16 → 27 not taken.
✓ Branch 17 → 18 taken 455 times.
✗ Branch 17 → 27 not taken.
✓ Branch 18 → 19 taken 455 times.
✗ Branch 18 → 27 not taken.
455 versionString << "built by: " << SPICE_BUILT_BY << "\n\n";
155
2/4
✓ Branch 19 → 20 taken 455 times.
✗ Branch 19 → 27 not taken.
✓ Branch 21 → 22 taken 455 times.
✗ Branch 21 → 27 not taken.
455 versionString << "(c) Marc Auberer 2021-" << getCurrentYear();
156
1/2
✓ Branch 22 → 23 taken 455 times.
✗ Branch 22 → 27 not taken.
910 return versionString.str();
157 455 }
158
159 } // namespace spice::compiler
160