Fix MJZ decoder Windows path separator issue

On Windows, std::filesystem::path::string() returns backslashes while
zip entries use forward slashes. This caused lookup mismatches making
MJZ decoding fail on Windows with 'could not decode content'.

Use generic_string() (which always returns forward slashes) for all
path operations used in zip entry lookups, and normalize the archive
name at construction time.

PiperOrigin-RevId: 943538265
Change-Id: I50cafff82fd7f5f315ccfc890f660e138e4448a2
This commit is contained in:
Sam Haves
2026-07-06 15:52:46 -07:00
committed by Copybara-Service
parent 528e791d6e
commit 19e175c063
+6 -4
View File
@@ -61,7 +61,8 @@ class ZipArchiveProvider : public mjpResourceProvider {
public: public:
ZipArchiveProvider(std::string name, const void* buffer, int nbuffer, ZipArchiveProvider(std::string name, const void* buffer, int nbuffer,
char* error, int error_sz) char* error, int error_sz)
: name_(std::move(name)), buffer_((char*)buffer, (char*)buffer + nbuffer) { : name_(std::filesystem::path(name).generic_string()),
buffer_((char*)buffer, (char*)buffer + nbuffer) {
mjp_defaultResourceProvider(this); mjp_defaultResourceProvider(this);
std::memset(&archive_, 0, sizeof(archive_)); std::memset(&archive_, 0, sizeof(archive_));
@@ -92,7 +93,8 @@ class ZipArchiveProvider : public mjpResourceProvider {
const std::filesystem::path path(name_); const std::filesystem::path path(name_);
root_model_ = (path / path.stem()).generic_string() + ".xml"; root_model_ = (path / path.stem()).generic_string() + ".xml";
if (!Contains(root_model_)) { if (!Contains(root_model_)) {
root_model_ = (path / path.stem() / path.stem()).string() + ".xml"; root_model_ =
(path / path.stem() / path.stem()).generic_string() + ".xml";
if (!Contains(root_model_)) { if (!Contains(root_model_)) {
SetError(error, error_sz, "Zip error: no root XML file found."); SetError(error, error_sz, "Zip error: no root XML file found.");
return; return;
@@ -111,13 +113,13 @@ class ZipArchiveProvider : public mjpResourceProvider {
open = [](mjResource* resource) { open = [](mjResource* resource) {
ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider; ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider;
auto path = std::filesystem::path(resource->name).lexically_normal(); auto path = std::filesystem::path(resource->name).lexically_normal();
const bool found = self->Contains(path.string()); const bool found = self->Contains(path.generic_string());
return found ? 1 : 0; return found ? 1 : 0;
}; };
read = [](mjResource* resource, const void** buffer) { read = [](mjResource* resource, const void** buffer) {
ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider; ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider;
auto path = std::filesystem::path(resource->name).lexically_normal(); auto path = std::filesystem::path(resource->name).lexically_normal();
std::span<char> bytes = self->Read(path.string()); std::span<char> bytes = self->Read(path.generic_string());
*buffer = bytes.data(); *buffer = bytes.data();
return static_cast<int>(bytes.size()); return static_cast<int>(bytes.size());
}; };