Don't print the fixed name ("main") of the top-level default class when saving XMLs.
Also insert newlines between top level sections in saved XML. PiperOrigin-RevId: 646802227 Change-Id: If16b93409bda88aee8ef75f4a78d7ba0419fcfae
This commit is contained in:
committed by
Copybara-Service
parent
6be4e0697e
commit
8c380e7ba4
@@ -69,7 +69,45 @@ static string WriteDoc(XMLDocument& doc, char *error, size_t error_sz) {
|
|||||||
mjCopyError(error, doc.ErrorStr(), error_sz);
|
mjCopyError(error, doc.ErrorStr(), error_sz);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return string(stream.CStr());
|
std::string str = string(stream.CStr());
|
||||||
|
|
||||||
|
// top level sections
|
||||||
|
auto sections = {"<actuator", "<asset", "<compiler", "<contact",
|
||||||
|
"<custom", "<default>", "<deformable", "<equality",
|
||||||
|
"<extension", "<keyframe", "<option", "<sensor",
|
||||||
|
"<size", "<statistic", "<tendon", "<visual",
|
||||||
|
"<worldbody"};
|
||||||
|
|
||||||
|
// position of newline before first section
|
||||||
|
size_t first_pos = std::string::npos;
|
||||||
|
|
||||||
|
// insert newlines before section headers
|
||||||
|
for (const std::string& section : sections) {
|
||||||
|
size_t pos = 0;
|
||||||
|
while ((pos = str.find(section, pos)) != std::string::npos) {
|
||||||
|
// find newline before this section
|
||||||
|
size_t line_pos = str.rfind('\n', pos);
|
||||||
|
|
||||||
|
// save position of first section
|
||||||
|
if (line_pos < first_pos) first_pos = line_pos;
|
||||||
|
|
||||||
|
// insert another newline
|
||||||
|
if (line_pos != std::string::npos) {
|
||||||
|
str.insert(line_pos + 1, "\n");
|
||||||
|
pos++; // account for inserted newline
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance
|
||||||
|
pos += section.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove added newline before the first section
|
||||||
|
if (first_pos != std::string::npos) {
|
||||||
|
str.erase(first_pos, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1143,7 +1181,9 @@ void mjXWriter::Default(XMLElement* root, mjCDef* def) {
|
|||||||
|
|
||||||
// create section, write class name
|
// create section, write class name
|
||||||
section = InsertEnd(root, "default");
|
section = InsertEnd(root, "default");
|
||||||
WriteAttrTxt(section, "class", def->name);
|
if (def->name != "main") {
|
||||||
|
WriteAttrTxt(section, "class", def->name);
|
||||||
|
}
|
||||||
|
|
||||||
// mesh
|
// mesh
|
||||||
elem = InsertEnd(section, "mesh");
|
elem = InsertEnd(section, "mesh");
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ TEST_F(MujocoTest, SaveXmlShortString) {
|
|||||||
|
|
||||||
std::array<char, 10> out;
|
std::array<char, 10> out;
|
||||||
EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(),
|
EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(),
|
||||||
error.data(), error.size()), 272);
|
error.data(), error.size()), 273);
|
||||||
EXPECT_STREQ(error.data(), "Output string too short, should be at least 273");
|
EXPECT_STREQ(error.data(), "Output string too short, should be at least 274");
|
||||||
|
|
||||||
mj_deleteSpec(spec);
|
mj_deleteSpec(spec);
|
||||||
mj_deleteModel(model);
|
mj_deleteModel(model);
|
||||||
@@ -139,7 +139,7 @@ TEST_F(MujocoTest, SaveXml) {
|
|||||||
mjModel* model = mj_compile(spec, 0);
|
mjModel* model = mj_compile(spec, 0);
|
||||||
EXPECT_THAT(model, NotNull()) << "Failed to compile model: " << error.data();
|
EXPECT_THAT(model, NotNull()) << "Failed to compile model: " << error.data();
|
||||||
|
|
||||||
std::array<char, 273> out;
|
std::array<char, 274> out;
|
||||||
EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(), error.data(),
|
EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(), error.data(),
|
||||||
error.size()), 0) << error.data();
|
error.size()), 0) << error.data();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user