Get the data path for a given path, searching the registered data.
23{
25
26
27 std::optional<std::pair<std::string, std::string>> explicit_data;
28 if (std::smatch match; std::regex_search(path, match, std::regex("(?:([a-z0-9_]+):)?(.*)")))
29 {
30
31 if (match[1].matched)
32 {
33 if (const auto it = data_paths.find(match[1].str()); it != data_paths.end())
34 explicit_data = *it;
35 else
36 mooseError(
"Data from '", match[1],
"' is not registered to be searched");
37 }
38 path = match[2];
39 }
40 else
41 mooseError(
"Failed to parse path '", path,
"'");
42
43 const std::filesystem::path value_path = std::filesystem::path(path);
44
45
46 const auto if_data_name_error = [&explicit_data](const auto & message)
47 {
48 if (explicit_data)
50 message,
51 " along with a data name to search (requested "
52 "to search in '",
53 explicit_data->first,
54 "')");
55 };
56
57
58 if (std::filesystem::path(path).is_absolute())
59 {
60
61 if_data_name_error("an absolute path");
62
63
66
67
70
71
72 mooseError(
"The absolute path '", path,
"' does not exist or is not readable.");
73 }
74
75
76 std::map<std::string, std::string> not_found;
77
78
79
80 if (!explicit_data)
81 {
82 const std::string base = options.
base ? *options.
base : std::filesystem::current_path().c_str();
84
85
88
89
90
91
94
95
97 }
98
99
100 std::optional<std::string> skip_data_reason;
101
102 if (path.size() > 1 && path.substr(0, 2) == "./")
103 {
104
105 if_data_name_error("a path that starts with './'");
106
107
108 skip_data_reason = "begins with './'";
109 }
110
111 else if (const std::string proximate = std::filesystem::proximate(path).c_str();
112 (proximate.size() > 1 && proximate.substr(0, 2) == ".."))
113 {
114
115 if_data_name_error("a relative path");
116
117
118 skip_data_reason = "resolves behind '.'";
119 }
120
121
122
123 std::map<std::string, std::string> found;
125 {
126 const auto check_data_path = [&found, ¬_found, &path](const auto & entry)
127 {
128 const auto & [
name, data_path] = entry;
132 else
133 not_found.emplace(name + " data", data_path);
134 };
135
136
137 if (explicit_data)
138 {
139 check_data_path(*explicit_data);
140 if (found.empty())
141 mooseError(
"The path '", path,
"' was not found in data from '", explicit_data->first,
"'");
142 }
143
144 else
145 {
146 for (const auto & entry : data_paths)
147 check_data_path(entry);
148 }
149 }
150
151
152 if (found.size() == 1)
153 {
154 const auto & [
name, data_path] = *found.begin();
156 }
157
158 std::stringstream oss;
159
160 if (found.size() > 1)
161 {
162 oss << "Multiple files were found when searching for the data file '" << path << "':\n\n";
163 for (const auto & [name, data_path] : found)
164 oss <<
" " <<
name <<
": " << data_path <<
"\n";
165 const auto & first_name = found.begin()->first;
166 oss << "\nYou can resolve this ambiguity by appending a prefix with the desired data name, for "
167 "example:\n\n "
168 << first_name << ":" << path;
169 }
170
171 else
172 {
173 oss << "Unable to find the data file '" << path << "'.\n";
174 if (not_found.size())
175 {
176 oss << "\nPaths searched:\n";
177 for (const auto & [name, data_path] : not_found)
178 oss <<
" " <<
name <<
": " << data_path <<
"\n";
179 }
180 if (skip_data_reason)
181 oss << "\nData path(s) were not searched because search path " << *skip_data_reason << ".\n";
182 }
183
185}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
static const std::map< std::string, std::string > & getDataFilePaths()
Returns a map of all registered data file paths (name -> path)
static Registry & getRegistry()
Get the global Registry singleton.
std::filesystem::path pathjoin(const std::filesystem::path &p)
std::string canonicalPath(const std::string &path)
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
std::string name(const ElemQuality q)
bool graceful
Whether or not to error whenever a path is not found.
std::optional< std::string > base
The base path by which to search for relative paths.
bool search_all_data
Whether or not to search all registered data.