Add ReadAttrVec, ReadAttrArr, ReadAttrStr, and ReadAttrNum to XML utils.

Moving forward, the compiler objects should have encapsulated data, therefore the old ReadAttr* methods are being deprecated as they require raw pointers to read into.

No external changes other than minor improvements to ReadAttr and ReadVector.

PiperOrigin-RevId: 550880401
Change-Id: I632f40322ccd935f9af9b69e66b056c5cda6face
This commit is contained in:
Kyle Bayes
2023-07-25 07:30:19 -07:00
committed by Copybara-Service
parent 5b4b3415fa
commit 5f246ef210
3 changed files with 212 additions and 105 deletions
+51 -5
View File
@@ -16,7 +16,9 @@
#ifndef MUJOCO_SRC_XML_XML_UTIL_H_
#define MUJOCO_SRC_XML_XML_UTIL_H_
// stl
#include <array>
#include <functional>
#include <optional>
#include <string>
#include <vector>
#include <sstream>
@@ -98,21 +100,60 @@ class mjXUtil {
// find value in map, return key ("": not found)
static std::string FindValue(const mjMap* map, int mapsz, int value);
// read any type from attribute, return number read
// if attribute is present, return vector of numerical data
template<typename T>
static std::optional<std::vector<T>> ReadAttrVec(tinyxml2::XMLElement* elem, const char* attr,
bool required = false);
// if attribute is present, return attribute as a string
static std::optional<std::string> ReadAttrStr(tinyxml2::XMLElement* elem, const char* attr,
bool required = false);
// if attribute is present, return numerical value of attribute
template<typename T>
static std::optional<T> ReadAttrNum(tinyxml2::XMLElement* elem, const char* attr,
bool required = false);
// if attribute is present, return array of numerical data
// N should be small as data is allocated on the stack
template<typename T, int N>
static std::optional<std::array<T, N>> ReadAttrArr(tinyxml2::XMLElement* elem, const char* attr,
bool required = false) {
std::array<T, N> arr;
int n = 0;
if (!ReadAttrValues<T>(elem, attr, [&](int i, T num) { arr[i] = num; n++; }, N)) {
throw mjXError(elem, "attribute '%s' has too much data", attr);
}
if (!n) {
if (required) {
throw mjXError(elem, "required attribute missing: '%s'", attr);
} else {
return std::nullopt;
}
}
if (n < N) {
throw mjXError(elem, "attribute '%s' does not have enough data", attr);
}
return arr;
}
// deprecated: use ReadAttrVec or ReadAttrArr
template<typename T>
static int ReadAttr(tinyxml2::XMLElement* elem, const char* attr, const int len,
T* data, std::string& text,
bool required = false, bool exact = true);
// read DOUBLE array into C++ vector, return number read
// deprecated: use ReadAttrVec
static int ReadVector(tinyxml2::XMLElement* elem, const char* attr,
std::vector<double>& vec, std::string& text, bool required = false);
// read text attribute
// deprecated: use ReadAttrStr
static bool ReadAttrTxt(tinyxml2::XMLElement* elem, const char* attr, std::string& text,
bool required = false);
// read int attribute
// deprecated: use ReadAttrNum
static bool ReadAttrInt(tinyxml2::XMLElement* elem, const char* attr, int* data,
bool required = false);
@@ -155,6 +196,11 @@ class mjXUtil {
// write attribute- keyword
static void WriteAttrKey(tinyxml2::XMLElement* elem, std::string name,
const mjMap* map, int mapsz, int data, int def = -12345);
private:
template<typename T>
static bool ReadAttrValues(tinyxml2::XMLElement* elem, const char* attr,
std::function<void (int, T)> push, int max = -1);
};
#endif // MUJOCO_SRC_XML_XML_UTIL_H_