Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add changes to enable searching for .msg files in sub-directories #1218

Open
wants to merge 7 commits into
base: rolling
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 49 additions & 6 deletions rosbag2_storage_mcap/src/message_definition_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ static const std::unordered_set<std::string> PRIMITIVE_TYPES{
"bool", "byte", "char", "float32", "float64", "int8", "uint8",
"int16", "uint16", "int32", "uint32", "int64", "uint64", "string"};

#ifdef _WIN32
static const char SEPARATOR[] = "\\";
#else
static const char SEPARATOR[] = "/";
#endif

static std::set<std::string> parse_msg_dependencies(const std::string & text,
const std::string & package_context)
{
Expand Down Expand Up @@ -119,6 +125,24 @@ static std::string delimiter(const DefinitionIdentifier & definition_identifier)
return result;
}

static std::vector<std::string> split_string(const std::string & str,
const std::string & delimiter = "\n")
{
std::vector<std::string> strings;
std::string::size_type pos = 0;
std::string::size_type prev = 0;

while ((pos = str.find(delimiter, prev)) != std::string::npos) {
strings.push_back(str.substr(prev, pos - prev));
prev = pos + delimiter.size();
}

// Get the last substring (or only, if delimiter is not found)
strings.push_back(str.substr(prev));

return strings;
}

MessageSpec::MessageSpec(Format format, std::string text, const std::string & package_context)
: dependencies(parse_dependencies(format, text, package_context))
, text(std::move(text))
Expand All @@ -139,15 +163,34 @@ const MessageSpec & MessageDefinitionCache::load_message_spec(
throw std::invalid_argument("Invalid package resource name: " +
definition_identifier.package_resource_name);
}
std::string package = match[1];
std::string share_dir = ament_index_cpp::get_package_share_directory(package);
std::ifstream file{share_dir + "/msg/" + match[2].str() +
extension_for_format(definition_identifier.format)};
if (!file.good()) {
const std::string package = match[1].str();
const std::string filename = match[2].str() + extension_for_format(definition_identifier.format);

// Get the package share directory, or throw a PackageNotFoundError
const std::string share_dir = ament_index_cpp::get_package_share_directory(package);

// Get the rosidl_interfaces index contents for this package
std::string index_contents;
if (!ament_index_cpp::get_resource("rosidl_interfaces", package, index_contents)) {
throw DefinitionNotFoundError(definition_identifier.package_resource_name);
}

std::string contents{std::istreambuf_iterator(file), {}};
// Find the first line that ends with the filename we're looking for
const auto lines = split_string(index_contents);
const auto it = std::find_if(lines.begin(), lines.end(), [&filename](const std::string & line) {
return line.size() >= filename.size() &&
line.compare(line.size() - filename.size(), filename.size(), filename) == 0;
});
if (it == lines.end()) {
throw DefinitionNotFoundError(definition_identifier.package_resource_name);
}

// Read the file
const std::string full_path = share_dir + SEPARATOR + *it;
std::ifstream file{full_path};

const std::string contents{std::istreambuf_iterator(file), {}};

const MessageSpec & spec =
msg_specs_by_definition_identifier_
.emplace(definition_identifier,
Expand Down