Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
ModelFileChecker.cpp
Go to the documentation of this file.
1#include "ModelFileChecker.h"
2
3#include <algorithm>
4#include <cctype>
5#include <iterator>
6#include <sstream>
7#include <unordered_set>
8
9ModelFileChecker::ModelFileChecker(const std::string& filePath) : filePath(filePath) {}
10
11std::string ModelFileChecker::readContents() const {
12 std::ifstream file(filePath);
13 if (!file.is_open()) {
14 throw std::runtime_error("Cannot open MARTY model file: " + filePath);
15 }
16
17 std::string contents((std::istreambuf_iterator<char>(file)), {});
18 contents.erase(std::remove(contents.begin(), contents.end(), '\r'), contents.end());
19 return contents;
20}
21
23 const std::string contents = readContents();
24 static const std::regex re(
25 R"((?:template\s*<[^>]*>\s*)class\s+[A-Za-z_]\w*\s*(?::|\{|$))",
26 std::regex::ECMAScript
27 );
28 return std::regex_search(contents, re);
29}
30
31std::vector<std::string> ModelFileChecker::modelClassCandidates(const std::string& model) {
32 auto to_upper = [](std::string s) {
33 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) {
34 return static_cast<char>(std::toupper(c));
35 });
36 return s;
37 };
38 auto to_lower = [](std::string s) {
39 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) {
40 return static_cast<char>(std::tolower(c));
41 });
42 return s;
43 };
44
45 const std::string upper = to_upper(model);
46 const std::string lower = to_lower(model);
47
48 std::vector<std::string> raw = {
49 model,
50 upper,
51 lower,
52 model + "_Model",
53 upper + "_Model",
54 lower + "_Model",
55 };
56
57 std::vector<std::string> out;
58 std::unordered_set<std::string> seen;
59 for (auto& candidate : raw) {
60 if (!candidate.empty() && seen.insert(candidate).second) {
61 out.emplace_back(std::move(candidate));
62 }
63 }
64 return out;
65}
66
67std::string ModelFileChecker::regexEscape(const std::string& value) {
68 std::string escaped;
69 escaped.reserve(value.size() * 2);
70 for (char c : value) {
71 switch (c) {
72 case '\\': case '^': case '$': case '.': case '|': case '?':
73 case '*': case '+': case '(': case ')': case '[': case ']':
74 case '{': case '}':
75 escaped.push_back('\\');
76 [[fallthrough]];
77 default:
78 escaped.push_back(c);
79 }
80 }
81 return escaped;
82}
83
84bool ModelFileChecker::hasClassDefinition(const std::string& contents,
85 const std::string& class_name,
86 bool& is_template) {
87 const std::string escaped = regexEscape(class_name);
88
89 const std::regex templated(
90 "(?:^|[\\s;{}])template\\s*<[^>]*>\\s*class\\s+" + escaped + R"(\b\s*(?:final\s*)?(?::|\{|$))",
91 std::regex::ECMAScript
92 );
93 if (std::regex_search(contents, templated)) {
94 is_template = true;
95 return true;
96 }
97
98 const std::regex plain(
99 "(?:^|[\\s;{}])class\\s+" + escaped + R"(\b\s*(?:final\s*)?(?::|\{|$))",
100 std::regex::ECMAScript
101 );
102 if (std::regex_search(contents, plain)) {
103 is_template = false;
104 return true;
105 }
106
107 return false;
108}
109
111 const std::string contents = readContents();
112 const auto candidates = modelClassCandidates(model);
113
114 for (const auto& candidate : candidates) {
115 bool is_template = false;
116 if (hasClassDefinition(contents, candidate, is_template)) {
117 return ModelClassInfo{candidate, is_template};
118 }
119 }
120
121 std::ostringstream oss;
122 for (std::size_t i = 0; i < candidates.size(); ++i) {
123 if (i != 0) {
124 oss << ", ";
125 }
126 oss << candidates[i];
127 }
128
129 throw std::runtime_error(
130 "Cannot resolve MARTY model class for mty_model_name='" + model +
131 "' in file '" + filePath + "'. Tried class names: " + oss.str() + "."
132 );
133}
Declares utilities to detect MARTY model classes in C++ files.
static std::vector< std::string > modelClassCandidates(const std::string &model)
Return the exact candidate sequence used by resolveModelClass.
ModelClassInfo resolveModelClass(const std::string &model) const
Resolve the concrete C++ class name for a user-provided model name.
bool isAnyModelTemplate() const
Tests whether the file contains any MARTY model template class.
ModelFileChecker(const std::string &filePath)
Constructs a checker for a given file path.