parse_xml.cpp: Deserilization does not touch lastError()
The global mLastError fields for each converters can
potentially cause a segfault when a program with multiple
threads tries to deserialize a bad file at the same time.
- deserialization APIs that touches the mLastError field are
marked as non-const APIs
- const variants are provided (error is provided as an output
parameter)
- Functionalities are equivalent (tests ensure this).
Test: libvintf_test
Test: vintf_object_test
Fixes: 71874788
Change-Id: I416de909b32809a4ac377d9da998c48d7d409457
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 7abbc55..739e344 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -143,50 +143,59 @@
virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags) const {
mutateNode(o, n, d);
}
- virtual bool buildObject(Object *o, NodeType *n) const = 0;
+ virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
virtual std::string elementName() const = 0;
// convenience methods for user
- inline const std::string &lastError() const { return mLastError; }
+ inline const std::string& lastError() const override { return mLastError; }
inline NodeType* serialize(const Object& o, DocType* d,
SerializeFlags flags = EVERYTHING) const {
NodeType *root = createNode(this->elementName(), d);
this->mutateNode(o, root, d, flags);
return root;
}
- inline std::string serialize(const Object& o, SerializeFlags flags) const {
+ inline std::string serialize(const Object& o, SerializeFlags flags) const override {
DocType *doc = createDocument();
appendChild(doc, serialize(o, doc, flags));
std::string s = printDocument(doc);
deleteDocument(doc);
return s;
}
- inline bool deserialize(Object *object, NodeType *root) const {
+ inline bool deserialize(Object* object, NodeType* root) {
+ bool ret = deserialize(object, root, &mLastError);
+ return ret;
+ }
+ inline bool deserialize(Object* o, const std::string& xml) override {
+ bool ret = (*this)(o, xml, &mLastError);
+ return ret;
+ }
+ inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
if (nameOf(root) != this->elementName()) {
return false;
}
- return this->buildObject(object, root);
+ return this->buildObject(object, root, error);
}
- inline bool deserialize(Object *o, const std::string &xml) const {
- DocType *doc = createDocument(xml);
+ inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
+ std::string errorBuffer;
+ if (error == nullptr) error = &errorBuffer;
+
+ auto doc = createDocument(xml);
if (doc == nullptr) {
- this->mLastError = "Not a valid XML";
+ *error = "Not a valid XML";
return false;
}
- bool ret = deserialize(o, getRootChild(doc));
+ bool ret = deserialize(o, getRootChild(doc), error);
deleteDocument(doc);
return ret;
}
inline NodeType *operator()(const Object &o, DocType *d) const {
return serialize(o, d);
}
- inline std::string operator()(const Object& o, SerializeFlags flags) const {
+ inline std::string operator()(const Object& o, SerializeFlags flags) const override {
return serialize(o, flags);
}
- inline bool operator()(Object *o, NodeType *node) const {
- return deserialize(o, node);
- }
- inline bool operator()(Object *o, const std::string &xml) const {
+ inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
+ inline bool operator()(Object* o, const std::string& xml) override {
return deserialize(o, xml);
}
@@ -230,11 +239,11 @@
}
// All parse* functions helps buildObject() to deserialize XML to the object. Returns
- // true if deserialization is successful, false if any error, and mLastError will be
+ // true if deserialization is successful, false if any error, and "error" will be
// set to error message.
template <typename T>
- inline bool parseOptionalAttr(NodeType *root, const std::string &attrName,
- T &&defaultValue, T *attr) const {
+ inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
+ T* attr, std::string* /* error */) const {
std::string attrText;
bool success = getAttr(root, attrName, &attrText) &&
::android::vintf::parse(attrText, attr);
@@ -245,31 +254,33 @@
}
template <typename T>
- inline bool parseAttr(NodeType *root, const std::string &attrName, T *attr) const {
+ inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
+ std::string* error) const {
std::string attrText;
bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
if (!ret) {
- mLastError = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
- attrText + "\" for element <" + elementName() + ">";
+ *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
+ attrText + "\" for element <" + elementName() + ">";
}
return ret;
}
- inline bool parseAttr(NodeType *root, const std::string &attrName, std::string *attr) const {
+ inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
+ std::string* error) const {
bool ret = getAttr(root, attrName, attr);
if (!ret) {
- mLastError = "Could not find attr with name \"" + attrName + "\" for element <"
- + elementName() + ">";
+ *error = "Could not find attr with name \"" + attrName + "\" for element <" +
+ elementName() + ">";
}
return ret;
}
- inline bool parseTextElement(NodeType *root,
- const std::string &elementName, std::string *s) const {
+ inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
+ std::string* error) const {
NodeType *child = getChild(root, elementName);
if (child == nullptr) {
- mLastError = "Could not find element with name <" + elementName + "> in element <"
- + this->elementName() + ">";
+ *error = "Could not find element with name <" + elementName + "> in element <" +
+ this->elementName() + ">";
return false;
}
*s = getText(child);
@@ -277,14 +288,15 @@
}
inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
- std::string&& defaultValue, std::string* s) const {
+ std::string&& defaultValue, std::string* s,
+ std::string* /* error */) const {
NodeType* child = getChild(root, elementName);
*s = child == nullptr ? std::move(defaultValue) : getText(child);
return true;
}
- inline bool parseTextElements(NodeType *root, const std::string &elementName,
- std::vector<std::string> *v) const {
+ inline bool parseTextElements(NodeType* root, const std::string& elementName,
+ std::vector<std::string>* v, std::string* /* error */) const {
auto nodes = getChildren(root, elementName);
v->resize(nodes.size());
for (size_t i = 0; i < nodes.size(); ++i) {
@@ -294,43 +306,37 @@
}
template <typename T>
- inline bool parseChild(NodeType *root, const XmlNodeConverter<T> &conv, T *t) const {
+ inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
+ std::string* error) const {
NodeType *child = getChild(root, conv.elementName());
if (child == nullptr) {
- mLastError = "Could not find element with name <" + conv.elementName() + "> in element <"
- + this->elementName() + ">";
+ *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
+ this->elementName() + ">";
return false;
}
- bool success = conv.deserialize(t, child);
- if (!success) {
- mLastError = conv.lastError();
- }
- return success;
+ return conv.deserialize(t, child, error);
}
template <typename T>
- inline bool parseOptionalChild(NodeType *root, const XmlNodeConverter<T> &conv,
- T &&defaultValue, T *t) const {
+ inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
+ T&& defaultValue, T* t, std::string* error) const {
NodeType *child = getChild(root, conv.elementName());
if (child == nullptr) {
*t = std::move(defaultValue);
return true;
}
- bool success = conv.deserialize(t, child);
- if (!success) {
- mLastError = conv.lastError();
- }
- return success;
+ return conv.deserialize(t, child, error);
}
template <typename T>
- inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::vector<T> *v) const {
+ inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
+ std::string* error) const {
auto nodes = getChildren(root, conv.elementName());
v->resize(nodes.size());
for (size_t i = 0; i < nodes.size(); ++i) {
- if (!conv.deserialize(&v->at(i), nodes[i])) {
- mLastError = "Could not parse element with name <" + conv.elementName()
- + "> in element <" + this->elementName() + ">: " + conv.lastError();
+ if (!conv.deserialize(&v->at(i), nodes[i], error)) {
+ *error = "Could not parse element with name <" + conv.elementName() +
+ "> in element <" + this->elementName() + ">: " + *error;
return false;
}
}
@@ -338,37 +344,39 @@
}
template <typename T>
- inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::set<T> *s) const {
+ inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::set<T>* s,
+ std::string* error) const {
std::vector<T> vec;
- if (!parseChildren(root, conv, &vec)) {
+ if (!parseChildren(root, conv, &vec, error)) {
return false;
}
s->clear();
s->insert(vec.begin(), vec.end());
if (s->size() != vec.size()) {
- mLastError = "Duplicated elements <" + conv.elementName() + "> in element <"
- + this->elementName() + ">";
+ *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
+ this->elementName() + ">";
s->clear();
return false;
}
return true;
}
- inline bool parseText(NodeType *node, std::string *s) const {
+ inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
*s = getText(node);
return true;
}
template <typename T>
- inline bool parseText(NodeType *node, T *s) const {
+ inline bool parseText(NodeType* node, T* s, std::string* error) const {
std::string text = getText(node);
bool ret = ::android::vintf::parse(text, s);
if (!ret) {
- mLastError = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
+ *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
}
return ret;
}
-protected:
+
+ private:
mutable std::string mLastError;
};
@@ -380,8 +388,8 @@
virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
appendText(root, ::android::vintf::to_string(object), d);
}
- virtual bool buildObject(Object *object, NodeType *root) const override {
- return this->parseText(root, object);
+ virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
+ return this->parseText(root, object, error);
}
virtual std::string elementName() const { return mElementName; };
private:
@@ -390,11 +398,11 @@
// ---------------------- XmlNodeConverter definitions end
-const XmlTextConverter<Version> versionConverter{"version"};
+XmlTextConverter<Version> versionConverter{"version"};
-const XmlTextConverter<VersionRange> versionRangeConverter{"version"};
+XmlTextConverter<VersionRange> versionRangeConverter{"version"};
-const XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
+XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
std::string elementName() const override { return "transport"; }
@@ -404,22 +412,22 @@
}
appendText(root, ::android::vintf::to_string(object.transport), d);
}
- bool buildObject(TransportArch *object, NodeType *root) const override {
- if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch) ||
- !parseText(root, &object->transport)) {
+ bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
+ if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
+ !parseText(root, &object->transport, error)) {
return false;
}
if (!object->isValid()) {
- this->mLastError = "transport == " + ::android::vintf::to_string(object->transport) +
- " and arch == " + ::android::vintf::to_string(object->arch) +
- " is not a valid combination.";
+ *error = "transport == " + ::android::vintf::to_string(object->transport) +
+ " and arch == " + ::android::vintf::to_string(object->arch) +
+ " is not a valid combination.";
return false;
}
return true;
}
};
-const TransportArchConverter transportArchConverter{};
+TransportArchConverter transportArchConverter{};
struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
std::string elementName() const override { return "value"; }
@@ -427,21 +435,22 @@
appendAttr(root, "type", object.mType);
appendText(root, ::android::vintf::to_string(object), d);
}
- bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override {
+ bool buildObject(KernelConfigTypedValue* object, NodeType* root,
+ std::string* error) const override {
std::string stringValue;
- if (!parseAttr(root, "type", &object->mType) ||
- !parseText(root, &stringValue)) {
+ if (!parseAttr(root, "type", &object->mType, error) ||
+ !parseText(root, &stringValue, error)) {
return false;
}
if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
- this->mLastError = "Could not parse kernel config value \"" + stringValue + "\"";
+ *error = "Could not parse kernel config value \"" + stringValue + "\"";
return false;
}
return true;
}
};
-const KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
+KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
std::string elementName() const override { return "config"; }
@@ -449,16 +458,16 @@
appendChild(root, kernelConfigKeyConverter(object.first, d));
appendChild(root, kernelConfigTypedValueConverter(object.second, d));
}
- bool buildObject(KernelConfig *object, NodeType *root) const override {
- if ( !parseChild(root, kernelConfigKeyConverter, &object->first)
- || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) {
+ bool buildObject(KernelConfig* object, NodeType* root, std::string* error) const override {
+ if (!parseChild(root, kernelConfigKeyConverter, &object->first, error) ||
+ !parseChild(root, kernelConfigTypedValueConverter, &object->second, error)) {
return false;
}
return true;
}
};
-const KernelConfigConverter kernelConfigConverter{};
+KernelConfigConverter kernelConfigConverter{};
struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
std::string elementName() const override { return "interface"; }
@@ -466,23 +475,23 @@
appendTextElement(root, "name", intf.name, d);
appendTextElements(root, "instance", intf.instances, d);
}
- bool buildObject(HalInterface *intf, NodeType *root) const override {
+ bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
std::vector<std::string> instances;
- if (!parseTextElement(root, "name", &intf->name) ||
- !parseTextElements(root, "instance", &instances)) {
+ if (!parseTextElement(root, "name", &intf->name, error) ||
+ !parseTextElements(root, "instance", &instances, error)) {
return false;
}
intf->instances.clear();
intf->instances.insert(instances.begin(), instances.end());
if (intf->instances.size() != instances.size()) {
- this->mLastError = "Duplicated instances in " + intf->name;
+ *error = "Duplicated instances in " + intf->name;
return false;
}
return true;
}
};
-const HalInterfaceConverter halInterfaceConverter{};
+HalInterfaceConverter halInterfaceConverter{};
struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
std::string elementName() const override { return "hal"; }
@@ -493,28 +502,29 @@
appendChildren(root, versionRangeConverter, hal.versionRanges, d);
appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
}
- bool buildObject(MatrixHal *object, NodeType *root) const override {
+ bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
std::vector<HalInterface> interfaces;
- if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
- !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional) ||
- !parseTextElement(root, "name", &object->name) ||
- !parseChildren(root, versionRangeConverter, &object->versionRanges) ||
- !parseChildren(root, halInterfaceConverter, &interfaces)) {
+ if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
+ !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
+ error) ||
+ !parseTextElement(root, "name", &object->name, error) ||
+ !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
+ !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
return false;
}
for (auto&& interface : interfaces) {
std::string name{interface.name};
auto res = object->interfaces.emplace(std::move(name), std::move(interface));
if (!res.second) {
- this->mLastError = "Duplicated interface entry \"" + res.first->first +
- "\"; if additional instances are needed, add them to the "
- "existing <interface> node.";
+ *error = "Duplicated interface entry \"" + res.first->first +
+ "\"; if additional instances are needed, add them to the "
+ "existing <interface> node.";
return false;
}
}
// Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
#ifndef LIBVINTF_TARGET
- if (!checkAdditionalRestrictionsOnHal(*object)) {
+ if (!checkAdditionalRestrictionsOnHal(*object, error)) {
return false;
}
#endif
@@ -523,24 +533,24 @@
#ifndef LIBVINTF_TARGET
private:
- bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal) const {
+ bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
if (hal.getName() == "netutils-wrapper") {
if (hal.versionRanges.size() != 1) {
- this->mLastError =
+ *error =
"netutils-wrapper HAL must specify exactly one version x.0, "
"but multiple <version> element is specified.";
return false;
}
const VersionRange& v = hal.versionRanges.at(0);
if (!v.isSingleVersion()) {
- this->mLastError =
+ *error =
"netutils-wrapper HAL must specify exactly one version x.0, "
"but a range is provided. Perhaps you mean '" +
to_string(Version{v.majorVer, 0}) + "'?";
return false;
}
if (v.minMinor != 0) {
- this->mLastError =
+ *error =
"netutils-wrapper HAL must specify exactly one version x.0, "
"but minor version is not 0. Perhaps you mean '" +
to_string(Version{v.majorVer, 0}) + "'?";
@@ -552,7 +562,7 @@
#endif
};
-const MatrixHalConverter matrixHalConverter{};
+MatrixHalConverter matrixHalConverter{};
struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
std::string elementName() const override { return "conditions"; }
@@ -560,12 +570,13 @@
DocType* d) const override {
appendChildren(root, kernelConfigConverter, conds, d);
}
- bool buildObject(std::vector<KernelConfig>* object, NodeType* root) const override {
- return parseChildren(root, kernelConfigConverter, object);
+ bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
+ std::string* error) const override {
+ return parseChildren(root, kernelConfigConverter, object, error);
}
};
-const MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
+MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
std::string elementName() const override { return "kernel"; }
@@ -576,17 +587,18 @@
}
appendChildren(root, kernelConfigConverter, kernel.mConfigs, d);
}
- bool buildObject(MatrixKernel *object, NodeType *root) const override {
- if (!parseAttr(root, "version", &object->mMinLts) ||
- !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions) ||
- !parseChildren(root, kernelConfigConverter, &object->mConfigs)) {
+ bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
+ if (!parseAttr(root, "version", &object->mMinLts, error) ||
+ !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
+ error) ||
+ !parseChildren(root, kernelConfigConverter, &object->mConfigs, error)) {
return false;
}
return true;
}
};
-const MatrixKernelConverter matrixKernelConverter{};
+MatrixKernelConverter matrixKernelConverter{};
struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
std::string elementName() const override { return "hal"; }
@@ -600,28 +612,27 @@
appendAttr(root, "override", hal.isOverride);
}
}
- bool buildObject(ManifestHal *object, NodeType *root) const override {
+ bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
std::vector<HalInterface> interfaces;
- if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
- !parseOptionalAttr(root, "override", false, &object->isOverride) ||
- !parseTextElement(root, "name", &object->name) ||
- !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch) ||
- !parseChildren(root, versionConverter, &object->versions) ||
- !parseChildren(root, halInterfaceConverter, &interfaces)) {
+ if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
+ !parseOptionalAttr(root, "override", false, &object->isOverride, error) ||
+ !parseTextElement(root, "name", &object->name, error) ||
+ !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
+ !parseChildren(root, versionConverter, &object->versions, error) ||
+ !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
return false;
}
switch (object->format) {
case HalFormat::HIDL: {
if (object->transportArch.empty()) {
- this->mLastError =
- "HIDL HAL '" + object->name + "' should have <transport> defined.";
+ *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
return false;
}
} break;
case HalFormat::NATIVE: {
if (!object->transportArch.empty()) {
- this->mLastError =
+ *error =
"Native HAL '" + object->name + "' should not have <transport> defined.";
return false;
}
@@ -639,19 +650,19 @@
auto res = object->interfaces.emplace(interface.name,
std::move(interface));
if (!res.second) {
- this->mLastError = "Duplicated interface entry \"" + res.first->first +
- "\"; if additional instances are needed, add them to the "
- "existing <interface> node.";
+ *error = "Duplicated interface entry \"" + res.first->first +
+ "\"; if additional instances are needed, add them to the "
+ "existing <interface> node.";
return false;
}
}
if (!object->isValid()) {
- this->mLastError = "'" + object->name + "' is not a valid Manifest HAL.";
+ *error = "'" + object->name + "' is not a valid Manifest HAL.";
return false;
}
// Do not check for target-side libvintf to avoid restricting upgrade accidentally.
#ifndef LIBVINTF_TARGET
- if (!checkAdditionalRestrictionsOnHal(*object)) {
+ if (!checkAdditionalRestrictionsOnHal(*object, error)) {
return false;
}
#endif
@@ -660,11 +671,11 @@
#ifndef LIBVINTF_TARGET
private:
- bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal) const {
+ bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
if (hal.getName() == "netutils-wrapper") {
for (const Version& v : hal.versions) {
if (v.minorVer != 0) {
- this->mLastError =
+ *error =
"netutils-wrapper HAL must specify exactly one version x.0, "
"but minor version is not 0. Perhaps you mean '" +
to_string(Version{v.majorVer, 0}) + "'?";
@@ -679,10 +690,10 @@
// Convert ManifestHal from and to XML. Returned object is guaranteed to have
// .isValid() == true.
-const ManifestHalConverter manifestHalConverter{};
+ManifestHalConverter manifestHalConverter{};
-const XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
-const XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
+XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
+XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
std::string elementName() const override { return "sepolicy"; }
@@ -690,21 +701,22 @@
appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
}
- bool buildObject(Sepolicy *object, NodeType *root) const override {
- if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion) ||
- !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges)) {
+ bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
+ if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
+ error) ||
+ !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
+ error)) {
return false;
}
return true;
}
};
-const SepolicyConverter sepolicyConverter{};
+SepolicyConverter sepolicyConverter{};
-[[deprecated]]
-const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
+[[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
-const XmlTextConverter<std::string> vndkVersionConverter{"version"};
-const XmlTextConverter<std::string> vndkLibraryConverter{"library"};
+XmlTextConverter<std::string> vndkVersionConverter{"version"};
+XmlTextConverter<std::string> vndkLibraryConverter{"library"};
struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
std::string elementName() const override { return "vndk"; }
@@ -712,17 +724,16 @@
appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
}
- bool buildObject(Vndk *object, NodeType *root) const override {
- if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange) ||
- !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) {
+ bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
+ if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
+ !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
return false;
}
return true;
}
};
-[[deprecated]]
-const VndkConverter vndkConverter{};
+[[deprecated]] VndkConverter vndkConverter{};
struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
std::string elementName() const override { return "vendor-ndk"; }
@@ -730,41 +741,41 @@
appendChild(root, vndkVersionConverter(object.mVersion, d));
appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
}
- bool buildObject(VendorNdk* object, NodeType* root) const override {
- if (!parseChild(root, vndkVersionConverter, &object->mVersion) ||
- !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) {
+ bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
+ if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
+ !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
return false;
}
return true;
}
};
-const VendorNdkConverter vendorNdkConverter{};
+VendorNdkConverter vendorNdkConverter{};
-const XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
+XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
std::string elementName() const override { return "system-sdk"; }
void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
appendChildren(root, systemSdkVersionConverter, object.versions(), d);
}
- bool buildObject(SystemSdk* object, NodeType* root) const override {
- return parseChildren(root, systemSdkVersionConverter, &object->mVersions);
+ bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
+ return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
}
};
-const SystemSdkConverter systemSdkConverter{};
+SystemSdkConverter systemSdkConverter{};
struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
std::string elementName() const override { return "sepolicy"; }
void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
appendChild(root, versionConverter(m, d));
}
- bool buildObject(Version *object, NodeType *root) const override {
- return parseChild(root, versionConverter, object);
+ bool buildObject(Version* object, NodeType* root, std::string* error) const override {
+ return parseChild(root, versionConverter, object, error);
}
};
-const HalManifestSepolicyConverter halManifestSepolicyConverter{};
+HalManifestSepolicyConverter halManifestSepolicyConverter{};
struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
std::string elementName() const override { return "xmlfile"; }
@@ -775,16 +786,16 @@
appendTextElement(root, "path", f.overriddenPath(), d);
}
}
- bool buildObject(ManifestXmlFile* object, NodeType* root) const override {
- if (!parseTextElement(root, "name", &object->mName) ||
- !parseChild(root, versionConverter, &object->mVersion) ||
- !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
+ bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
+ if (!parseTextElement(root, "name", &object->mName, error) ||
+ !parseChild(root, versionConverter, &object->mVersion, error) ||
+ !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
return false;
}
return true;
}
};
-const ManifestXmlFileConverter manifestXmlFileConverter{};
+ManifestXmlFileConverter manifestXmlFileConverter{};
struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
std::string elementName() const override { return "manifest"; }
@@ -826,17 +837,17 @@
appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
}
}
- bool buildObject(HalManifest *object, NodeType *root) const override {
+ bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
std::vector<ManifestHal> hals;
- if (!parseAttr(root, "version", &object->mMetaVersion) ||
- !parseAttr(root, "type", &object->mType) ||
- !parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel) ||
- !parseChildren(root, manifestHalConverter, &hals)) {
+ if (!parseAttr(root, "version", &object->mMetaVersion, error) ||
+ !parseAttr(root, "type", &object->mType, error) ||
+ !parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel, error) ||
+ !parseChildren(root, manifestHalConverter, &hals, error)) {
return false;
}
if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) {
- this->mLastError = "Unrecognized manifest.version " + to_string(object->mMetaVersion) +
- " (libvintf@" + to_string(kMetaVersion) + ")";
+ *error = "Unrecognized manifest.version " + to_string(object->mMetaVersion) +
+ " (libvintf@" + to_string(kMetaVersion) + ")";
return false;
}
if (object->mType == SchemaType::DEVICE) {
@@ -844,59 +855,59 @@
// <sepolicy> can be missing because it can be determined at build time, not hard-coded
// in the XML file.
if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
- &object->device.mSepolicyVersion)) {
+ &object->device.mSepolicyVersion, error)) {
return false;
}
} else if (object->mType == SchemaType::FRAMEWORK) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) {
+ if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
return false;
}
for (const auto &vndk : object->framework.mVndks) {
if (!vndk.mVersionRange.isSingleVersion()) {
- this->mLastError = "vndk.version " + to_string(vndk.mVersionRange)
- + " cannot be a range for manifests";
+ *error = "vndk.version " + to_string(vndk.mVersionRange) +
+ " cannot be a range for manifests";
return false;
}
}
#pragma clang diagnostic pop
- if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks)) {
+ if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
return false;
}
std::set<std::string> vendorNdkVersions;
for (const auto& vendorNdk : object->framework.mVendorNdks) {
if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
- this->mLastError =
- "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
+ *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
return false;
}
vendorNdkVersions.insert(vendorNdk.version());
}
- if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk)) {
+ if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
+ error)) {
return false;
}
}
for (auto &&hal : hals) {
std::string description{hal.name};
if (!object->add(std::move(hal))) {
- this->mLastError = "Duplicated manifest.hal entry " + description;
+ *error = "Duplicated manifest.hal entry " + description;
return false;
}
}
std::vector<ManifestXmlFile> xmlFiles;
- if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles)) {
+ if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
return false;
}
for (auto&& xmlFile : xmlFiles) {
std::string description{xmlFile.name()};
if (!object->addXmlFile(std::move(xmlFile))) {
- this->mLastError = "Duplicated manifest.xmlfile entry " + description +
- "; entries cannot have duplicated name and version";
+ *error = "Duplicated manifest.xmlfile entry " + description +
+ "; entries cannot have duplicated name and version";
return false;
}
}
@@ -905,19 +916,19 @@
}
};
-const HalManifestConverter halManifestConverter{};
+HalManifestConverter halManifestConverter{};
-const XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
+XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
struct AvbConverter : public XmlNodeConverter<Version> {
std::string elementName() const override { return "avb"; }
void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
appendChild(root, avbVersionConverter(m, d));
}
- bool buildObject(Version *object, NodeType *root) const override {
- return parseChild(root, avbVersionConverter, object);
+ bool buildObject(Version* object, NodeType* root, std::string* error) const override {
+ return parseChild(root, avbVersionConverter, object, error);
}
};
-const AvbConverter avbConverter{};
+AvbConverter avbConverter{};
struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
std::string elementName() const override { return "xmlfile"; }
@@ -930,18 +941,18 @@
appendTextElement(root, "path", f.overriddenPath(), d);
}
}
- bool buildObject(MatrixXmlFile* object, NodeType* root) const override {
- if (!parseTextElement(root, "name", &object->mName) ||
- !parseAttr(root, "format", &object->mFormat) ||
- !parseOptionalAttr(root, "optional", false, &object->mOptional) ||
- !parseChild(root, versionRangeConverter, &object->mVersionRange) ||
- !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
+ bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
+ if (!parseTextElement(root, "name", &object->mName, error) ||
+ !parseAttr(root, "format", &object->mFormat, error) ||
+ !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
+ !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
+ !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
return false;
}
return true;
}
};
-const MatrixXmlFileConverter matrixXmlFileConverter{};
+MatrixXmlFileConverter matrixXmlFileConverter{};
struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
std::string elementName() const override { return "compatibility-matrix"; }
@@ -998,21 +1009,25 @@
appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
}
}
- bool buildObject(CompatibilityMatrix *object, NodeType *root) const override {
+ bool buildObject(CompatibilityMatrix* object, NodeType* root,
+ std::string* error) const override {
Version version;
std::vector<MatrixHal> hals;
- if (!parseAttr(root, "version", &version) || !parseAttr(root, "type", &object->mType) ||
- !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel) ||
- !parseChildren(root, matrixHalConverter, &hals)) {
+ if (!parseAttr(root, "version", &version, error) ||
+ !parseAttr(root, "type", &object->mType, error) ||
+ !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error) ||
+ !parseChildren(root, matrixHalConverter, &hals, error)) {
return false;
}
if (object->mType == SchemaType::FRAMEWORK) {
// <avb> and <sepolicy> can be missing because it can be determined at build time, not
// hard-coded in the XML file.
- if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels) ||
- !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy) ||
- !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion)) {
+ if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
+ !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
+ error) ||
+ !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
+ error)) {
return false;
}
@@ -1023,8 +1038,8 @@
continue;
}
if (!kernel.conditions().empty()) {
- this->mLastError = "First <kernel> for version " + to_string(minLts) +
- " must have empty <conditions> for backwards compatibility.";
+ *error = "First <kernel> for version " + to_string(minLts) +
+ " must have empty <conditions> for backwards compatibility.";
return false;
}
seenKernelVersions.insert(minLts);
@@ -1035,45 +1050,47 @@
// in the XML file.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) {
+ if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
return false;
}
#pragma clang diagnostic pop
- if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk)) {
+ if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
+ error)) {
return false;
}
- if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk)) {
+ if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
+ error)) {
return false;
}
}
if (!kMetaVersion.minorAtLeast(version)) {
- this->mLastError = "Unrecognized compatibility-matrix.version " + to_string(version) +
- " (libvintf@" + to_string(kMetaVersion) + ")";
+ *error = "Unrecognized compatibility-matrix.version " + to_string(version) +
+ " (libvintf@" + to_string(kMetaVersion) + ")";
return false;
}
for (auto &&hal : hals) {
if (!object->add(std::move(hal))) {
- this->mLastError = "Duplicated compatibility-matrix.hal entry";
+ *error = "Duplicated compatibility-matrix.hal entry";
return false;
}
}
std::vector<MatrixXmlFile> xmlFiles;
- if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles)) {
+ if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
return false;
}
for (auto&& xmlFile : xmlFiles) {
if (!xmlFile.optional()) {
- this->mLastError = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
- " has to be optional for compatibility matrix version 1.0";
+ *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
+ " has to be optional for compatibility matrix version 1.0";
return false;
}
std::string description{xmlFile.name()};
if (!object->addXmlFile(std::move(xmlFile))) {
- this->mLastError = "Duplicated compatibility-matrix.xmlfile entry " + description;
+ *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
return false;
}
}
@@ -1082,19 +1099,18 @@
}
};
-const CompatibilityMatrixConverter compatibilityMatrixConverter{};
+CompatibilityMatrixConverter compatibilityMatrixConverter{};
// Publicly available as in parse_xml.h
-const XmlConverter<HalManifest> &gHalManifestConverter = halManifestConverter;
-const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter
- = compatibilityMatrixConverter;
+XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
+XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
// For testing in LibVintfTest
-const XmlConverter<Version> &gVersionConverter = versionConverter;
-const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter
- = kernelConfigTypedValueConverter;
-const XmlConverter<MatrixHal> &gMatrixHalConverter = matrixHalConverter;
-const XmlConverter<ManifestHal> &gManifestHalConverter = manifestHalConverter;
+XmlConverter<Version>& gVersionConverter = versionConverter;
+XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
+ kernelConfigTypedValueConverter;
+XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
+XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
} // namespace vintf
} // namespace android