Add content_type attribute that takes a MIME type to specify the file contents for meshes, hfields, and textures.

PiperOrigin-RevId: 549302344
Change-Id: I30a8adfef5b5d87bb20479329f3396892f5137ff
This commit is contained in:
Kyle Bayes
2023-07-19 06:50:35 -07:00
committed by Copybara-Service
parent 5f327b0c31
commit 5fcdae771b
12 changed files with 556 additions and 44 deletions
+81
View File
@@ -18,12 +18,14 @@
#include <cstddef>
#include <cstdio>
#include <limits>
#include <optional>
#include <string>
#include <string_view>
#include <mujoco/mjmacro.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mujoco.h>
#include "engine/engine_crossplatform.h"
#include "engine/engine_util_spatial.h"
using std::isnan;
@@ -596,3 +598,82 @@ string mjuu_makefullname(string filedir, string meshdir, string filename) {
// default
return filedir + meshdir + filename;
}
// return true if the text is in a valid content type format:
// {type}/{subtype}[;{parameter}={value}]
static bool mjuu_isValidContentType(std::string_view text) {
// find a forward slash that's not the last character
size_t n = text.find('/');
if (n == std::string::npos || n == text.size() - 1) {
return false;
}
size_t m = text.find(';');
if (m == std::string::npos) {
return true;
}
if (m + 1 <= n) {
return false;
}
// just check if there's an equal sign; this isn't robust enough for general
// validation, but works for our scope, hence this is a private helper
// function
size_t s = text.find('=');
if (s == std::string::npos || s + 1 <= m) {
return false;
}
return true;
}
// return type from content_type format {type}/{subtype}[;{parameter}={value}]
// return empty string on invalid format
std::optional<std::string_view> mjuu_parseContentTypeAttrType(std::string_view text) {
if (!mjuu_isValidContentType(text)) {
return std::nullopt;
}
return { text.substr(0, text.find('/')) };
}
// return subtype from content_type format {type}/{subtype}[;{parameter}={value}]
// return empty string on invalid format
std::optional<std::string_view> mjuu_parseContentTypeAttrSubtype(std::string_view text) {
if (!mjuu_isValidContentType(text)) {
return std::nullopt;
}
size_t n = text.find('/');
size_t m = text.find(';', n + 1);
if (m == std::string::npos) {
return { text.substr(n+1) };
}
return { text.substr(n + 1, m - n - 1) };
}
// convert filename extension to content type; return empty string if not found
std::string mjuu_extToContentType(std::string_view filename) {
std::string ext = mjuu_getext(filename);
if (!strcasecmp(ext.c_str(), ".stl")) {
return "model/stl";
} else if (!strcasecmp(ext.c_str(), ".obj")) {
return "model/obj";
} else if (!strcasecmp(ext.c_str(), ".msh")) {
return "model/vnd.mujoco.msh";
} else if (!strcasecmp(ext.c_str(), ".png")) {
return "image/png";
} else {
return "";
}
}