forked from pz4kybsvg/Conception
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.8 KiB
94 lines
2.8 KiB
#include "drake/multibody/parsing/detail_path_utils.h"
|
|
|
|
#include <filesystem>
|
|
#include <optional>
|
|
#include <regex>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <fmt/format.h>
|
|
|
|
#include "drake/common/drake_assert.h"
|
|
#include "drake/common/never_destroyed.h"
|
|
|
|
namespace drake {
|
|
namespace multibody {
|
|
namespace internal {
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
using std::string;
|
|
using drake::internal::DiagnosticPolicy;
|
|
|
|
string ResolveUri(const DiagnosticPolicy& diagnostic, const string& uri,
|
|
const PackageMap& package_map, const string& root_dir) {
|
|
fs::path result;
|
|
|
|
// Parse the given URI into pieces.
|
|
static const never_destroyed<std::regex> uri_matcher{
|
|
"^([a-z0-9+.-]+)://([^/]*)/+(.*)"};
|
|
std::smatch match;
|
|
if (std::regex_match(uri, match, uri_matcher.access())) {
|
|
// The `uri` was actually a URI (not a bare filename).
|
|
DRAKE_DEMAND(match.size() == 4);
|
|
const std::string& uri_scheme = match[1];
|
|
const std::string& uri_package = match[2];
|
|
const std::string& uri_path = match[3];
|
|
if (uri_scheme == "file") {
|
|
result = "/" + uri_path;
|
|
} else if ((uri_scheme == "model") || (uri_scheme == "package")) {
|
|
if (!package_map.Contains(uri_package)) {
|
|
diagnostic.Error(fmt::format(
|
|
"URI '{}' refers to unknown package '{}'", uri, uri_package));
|
|
return {};
|
|
}
|
|
std::optional<string> deprecation;
|
|
const std::string& package_path = package_map.GetPath(
|
|
uri_package, &deprecation);
|
|
if (deprecation.has_value()) {
|
|
diagnostic.Warning(fmt::format(
|
|
"In URI '{}': {}", uri, *deprecation));
|
|
}
|
|
result = fs::path(package_path) / uri_path;
|
|
} else {
|
|
diagnostic.Error(fmt::format(
|
|
"URI '{}' specifies an unsupported scheme; supported schemes are "
|
|
"'file://', 'model://', and 'package://'.", uri));
|
|
return {};
|
|
}
|
|
} else {
|
|
if (root_dir.empty()) {
|
|
diagnostic.Error(fmt::format(
|
|
"URI '{}' is invalid when parsing a string instead of a filename.",
|
|
uri));
|
|
return {};
|
|
}
|
|
// Strictly speaking a URI should not just be a bare filename, but we allow
|
|
// this for backward compatibility and user convenience.
|
|
const string& filename = uri;
|
|
if (fs::path(filename).is_absolute()) {
|
|
result = filename;
|
|
} else if (fs::path(root_dir).is_absolute()) {
|
|
result = root_dir;
|
|
result.append(filename);
|
|
} else {
|
|
result = fs::current_path() / root_dir / filename;
|
|
}
|
|
}
|
|
|
|
result = result.lexically_normal();
|
|
|
|
if (!fs::exists(result)) {
|
|
diagnostic.Error(fmt::format(
|
|
"URI '{}' resolved to '{}' which does not exist.",
|
|
uri, result.string()));
|
|
return {};
|
|
}
|
|
|
|
return result.string();
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace multibody
|
|
} // namespace drake
|