Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | // Convert objects from and to xml. |
| 18 | |
| 19 | #include <tinyxml2.h> |
| 20 | |
| 21 | #include "parse_string.h" |
| 22 | #include "parse_xml.h" |
| 23 | |
| 24 | namespace android { |
| 25 | namespace vintf { |
| 26 | |
| 27 | // --------------- tinyxml2 details |
| 28 | |
| 29 | using NodeType = tinyxml2::XMLElement; |
| 30 | using DocType = tinyxml2::XMLDocument; |
| 31 | |
| 32 | // caller is responsible for deleteDocument() call |
| 33 | inline DocType *createDocument() { |
| 34 | return new tinyxml2::XMLDocument(); |
| 35 | } |
| 36 | |
| 37 | // caller is responsible for deleteDocument() call |
| 38 | inline DocType *createDocument(const std::string &xml) { |
| 39 | DocType *doc = new tinyxml2::XMLDocument(); |
| 40 | if (doc->Parse(xml.c_str()) == tinyxml2::XML_NO_ERROR) { |
| 41 | return doc; |
| 42 | } |
| 43 | delete doc; |
| 44 | return nullptr; |
| 45 | } |
| 46 | |
| 47 | inline void deleteDocument(DocType *d) { |
| 48 | delete d; |
| 49 | } |
| 50 | |
| 51 | inline std::string printDocument(DocType *d) { |
| 52 | tinyxml2::XMLPrinter p; |
| 53 | d->Print(&p); |
| 54 | return std::string{p.CStr()}; |
| 55 | } |
| 56 | |
| 57 | inline NodeType *createNode(const std::string &name, DocType *d) { |
| 58 | return d->NewElement(name.c_str()); |
| 59 | } |
| 60 | |
| 61 | inline void appendChild(NodeType *parent, NodeType *child) { |
| 62 | parent->InsertEndChild(child); |
| 63 | } |
| 64 | |
| 65 | inline void appendChild(DocType *parent, NodeType *child) { |
| 66 | parent->InsertEndChild(child); |
| 67 | } |
| 68 | |
| 69 | inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) { |
| 70 | e->SetAttribute(attrName.c_str(), attr.c_str()); |
| 71 | } |
| 72 | |
| 73 | // text -> text |
| 74 | inline void appendText(NodeType *parent, const std::string &text, DocType *d) { |
| 75 | parent->InsertEndChild(d->NewText(text.c_str())); |
| 76 | } |
| 77 | |
| 78 | // text -> <name>text</name> |
| 79 | inline void appendTextElement(NodeType *parent, const std::string &name, |
| 80 | const std::string &text, DocType *d) { |
| 81 | NodeType *c = createNode(name, d); |
| 82 | appendText(c, text, d); |
| 83 | appendChild(parent, c); |
| 84 | } |
| 85 | |
| 86 | inline std::string nameOf(NodeType *root) { |
Yifan Hong | cd41ffc | 2017-01-20 13:46:32 -0800 | [diff] [blame] | 87 | return root->Name() == NULL ? "" : root->Name(); |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 88 | } |
| 89 | |
| 90 | inline std::string getText(NodeType *root) { |
Yifan Hong | cd41ffc | 2017-01-20 13:46:32 -0800 | [diff] [blame] | 91 | return root->GetText() == NULL ? "" : root->GetText(); |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | inline NodeType *getChild(NodeType *parent, const std::string &name) { |
| 95 | return parent->FirstChildElement(name.c_str()); |
| 96 | } |
| 97 | |
| 98 | inline NodeType *getRootChild(DocType *parent) { |
| 99 | return parent->FirstChildElement(); |
| 100 | } |
| 101 | |
| 102 | inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) { |
| 103 | std::vector<NodeType *> v; |
| 104 | for (NodeType *child = parent->FirstChildElement(name.c_str()); |
| 105 | child != nullptr; |
| 106 | child = child->NextSiblingElement(name.c_str())) { |
| 107 | v.push_back(child); |
| 108 | } |
| 109 | return v; |
| 110 | } |
| 111 | |
| 112 | inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) { |
| 113 | const char *c = root->Attribute(attrName.c_str()); |
| 114 | if (c == NULL) |
| 115 | return false; |
| 116 | *s = c; |
| 117 | return true; |
| 118 | } |
| 119 | |
| 120 | // --------------- tinyxml2 details end. |
| 121 | |
| 122 | // ---------------------- XmlNodeConverter definitions |
| 123 | |
| 124 | template<typename Object> |
| 125 | struct XmlNodeConverter : public XmlConverter<Object> { |
| 126 | XmlNodeConverter() {} |
| 127 | virtual ~XmlNodeConverter() {} |
| 128 | |
| 129 | // sub-types should implement these. |
| 130 | virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0; |
| 131 | virtual bool buildObject(Object *o, NodeType *n) const = 0; |
| 132 | virtual std::string elementName() const = 0; |
| 133 | |
| 134 | // convenience methods for user |
| 135 | inline const std::string &lastError() const { return mLastError; } |
| 136 | inline NodeType *serialize(const Object &o, DocType *d) const { |
| 137 | NodeType *root = createNode(this->elementName(), d); |
| 138 | this->mutateNode(o, root, d); |
| 139 | return root; |
| 140 | } |
| 141 | inline std::string serialize(const Object &o) const { |
| 142 | DocType *doc = createDocument(); |
| 143 | appendChild(doc, serialize(o, doc)); |
| 144 | std::string s = printDocument(doc); |
| 145 | deleteDocument(doc); |
| 146 | return s; |
| 147 | } |
| 148 | inline bool deserialize(Object *object, NodeType *root) const { |
| 149 | if (nameOf(root) != this->elementName()) { |
| 150 | return false; |
| 151 | } |
| 152 | return this->buildObject(object, root); |
| 153 | } |
| 154 | inline bool deserialize(Object *o, const std::string &xml) const { |
| 155 | DocType *doc = createDocument(xml); |
| 156 | bool ret = doc != nullptr |
| 157 | && deserialize(o, getRootChild(doc)); |
| 158 | deleteDocument(doc); |
| 159 | return ret; |
| 160 | } |
| 161 | inline NodeType *operator()(const Object &o, DocType *d) const { |
| 162 | return serialize(o, d); |
| 163 | } |
| 164 | inline std::string operator()(const Object &o) const { |
| 165 | return serialize(o); |
| 166 | } |
| 167 | inline bool operator()(Object *o, NodeType *node) const { |
| 168 | return deserialize(o, node); |
| 169 | } |
| 170 | inline bool operator()(Object *o, const std::string &xml) const { |
| 171 | return deserialize(o, xml); |
| 172 | } |
| 173 | |
| 174 | // convenience methods for implementor. |
| 175 | template <typename T> |
| 176 | inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const { |
| 177 | return appendStrAttr(e, attrName, ::android::vintf::to_string(attr)); |
| 178 | } |
| 179 | |
| 180 | inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const { |
| 181 | return appendStrAttr(e, attrName, attr ? "true" : "false"); |
| 182 | } |
| 183 | |
| 184 | template <typename T> |
| 185 | inline bool parseAttr(NodeType *root, const std::string &attrName, T *attr) const { |
| 186 | std::string attrText; |
| 187 | bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr); |
| 188 | if (!ret) { |
| 189 | mLastError = "Could not parse attr with name " + attrName; |
| 190 | } |
| 191 | return ret; |
| 192 | } |
| 193 | |
| 194 | inline bool parseAttr(NodeType *root, const std::string &attrName, std::string *attr) const { |
| 195 | bool ret = getAttr(root, attrName, attr); |
| 196 | if (!ret) { |
| 197 | mLastError = "Could not find attr with name " + attrName; |
| 198 | } |
| 199 | return ret; |
| 200 | } |
| 201 | |
| 202 | inline bool parseAttr(NodeType *root, const std::string &attrName, bool *attr) const { |
| 203 | std::string attrText; |
| 204 | if (!getAttr(root, attrName, &attrText)) { |
| 205 | mLastError = "Could not find attr with name " + attrName; |
| 206 | return false; |
| 207 | } |
| 208 | if (attrText == "true" || attrText == "1") { |
| 209 | *attr = true; |
| 210 | return true; |
| 211 | } |
| 212 | if (attrText == "false" || attrText == "0") { |
| 213 | *attr = false; |
| 214 | return true; |
| 215 | } |
| 216 | mLastError = "Could not parse attr with name \"" + attrName |
| 217 | + "\" and value \"" + attrText + "\""; |
| 218 | return false; |
| 219 | } |
| 220 | |
| 221 | inline bool parseTextElement(NodeType *root, |
| 222 | const std::string &elementName, std::string *s) const { |
| 223 | NodeType *child = getChild(root, elementName); |
| 224 | if (child == nullptr) { |
| 225 | mLastError = "Could not find element with name " + elementName; |
| 226 | return false; |
| 227 | } |
| 228 | *s = getText(child); |
| 229 | return true; |
| 230 | } |
| 231 | |
| 232 | template <typename T> |
| 233 | inline bool parseChild(NodeType *root, const XmlNodeConverter<T> &conv, T *t) const { |
| 234 | NodeType *child = getChild(root, conv.elementName()); |
| 235 | if (child == nullptr) { |
| 236 | mLastError = "Could not find element with name " + conv.elementName(); |
| 237 | return false; |
| 238 | } |
| 239 | bool success = conv.deserialize(t, child); |
| 240 | if (!success) { |
| 241 | mLastError = conv.lastError(); |
| 242 | } |
| 243 | return success; |
| 244 | } |
| 245 | |
| 246 | template <typename T> |
| 247 | inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::vector<T> *v) const { |
| 248 | auto nodes = getChildren(root, conv.elementName()); |
| 249 | v->resize(nodes.size()); |
| 250 | for (size_t i = 0; i < nodes.size(); ++i) { |
| 251 | if (!conv.deserialize(&v->at(i), nodes[i])) { |
| 252 | mLastError = "Could not parse element with name " + conv.elementName(); |
| 253 | return false; |
| 254 | } |
| 255 | } |
| 256 | return true; |
| 257 | } |
| 258 | |
| 259 | inline bool parseText(NodeType *node, std::string *s) const { |
| 260 | *s = getText(node); |
| 261 | return true; |
| 262 | } |
| 263 | |
| 264 | protected: |
| 265 | mutable std::string mLastError; |
| 266 | }; |
| 267 | |
| 268 | template<typename Object> |
| 269 | struct XmlTextConverter : public XmlNodeConverter<Object> { |
| 270 | XmlTextConverter(const std::string &elementName) |
| 271 | : mElementName(elementName) {} |
| 272 | |
| 273 | virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override { |
| 274 | appendText(root, ::android::vintf::to_string(object), d); |
| 275 | } |
| 276 | virtual bool buildObject(Object *object, NodeType *root) const override { |
| 277 | std::string text = getText(root); |
| 278 | bool ret = ::android::vintf::parse(text, object); |
| 279 | if (!ret) { |
| 280 | this->mLastError = "Could not parse " + text; |
| 281 | } |
| 282 | return ret; |
| 283 | } |
| 284 | virtual std::string elementName() const { return mElementName; }; |
| 285 | private: |
| 286 | std::string mElementName; |
| 287 | }; |
| 288 | |
| 289 | // ---------------------- XmlNodeConverter definitions end |
| 290 | |
| 291 | const XmlTextConverter<Version> versionConverter{"version"}; |
| 292 | const XmlConverter<Version> &gVersionConverter = versionConverter; |
| 293 | |
| 294 | const XmlTextConverter<VersionRange> versionRangeConverter{"version"}; |
| 295 | const XmlConverter<VersionRange> &gVersionRangeConverter = versionRangeConverter; |
| 296 | |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 297 | const XmlTextConverter<Transport> transportConverter{"transport"}; |
| 298 | const XmlConverter<Transport> &gTransportConverter = transportConverter; |
| 299 | |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 300 | const XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"}; |
| 301 | |
| 302 | struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> { |
| 303 | std::string elementName() const override { return "value"; } |
| 304 | void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override { |
| 305 | appendAttr(root, "type", object.mType); |
| 306 | appendText(root, ::android::vintf::to_string(object), d); |
| 307 | } |
| 308 | bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override { |
| 309 | std::string stringValue; |
| 310 | if (!parseAttr(root, "type", &object->mType) || |
| 311 | !parseText(root, &stringValue)) { |
| 312 | return false; |
| 313 | } |
| 314 | if (!::android::vintf::parseKernelConfigValue(stringValue, object)) { |
| 315 | return false; |
| 316 | } |
| 317 | return true; |
| 318 | } |
| 319 | }; |
| 320 | |
| 321 | const KernelConfigTypedValueConverter kernelConfigTypedValueConverter{}; |
| 322 | const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter = kernelConfigTypedValueConverter; |
| 323 | |
| 324 | struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> { |
| 325 | std::string elementName() const override { return "config"; } |
| 326 | void mutateNode(const KernelConfig &object, NodeType *root, DocType *d) const override { |
| 327 | appendChild(root, kernelConfigKeyConverter(object.first, d)); |
| 328 | appendChild(root, kernelConfigTypedValueConverter(object.second, d)); |
| 329 | } |
| 330 | bool buildObject(KernelConfig *object, NodeType *root) const override { |
| 331 | if ( !parseChild(root, kernelConfigKeyConverter, &object->first) |
| 332 | || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) { |
| 333 | return false; |
| 334 | } |
| 335 | return true; |
| 336 | } |
| 337 | }; |
| 338 | |
| 339 | const KernelConfigConverter kernelConfigConverter{}; |
| 340 | |
Yifan Hong | a999357 | 2017-01-24 19:33:15 -0800 | [diff] [blame] | 341 | struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 342 | std::string elementName() const override { return "hal"; } |
| 343 | void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override { |
| 344 | appendAttr(root, "format", hal.format); |
| 345 | appendAttr(root, "optional", hal.optional); |
| 346 | appendTextElement(root, "name", hal.name, d); |
| 347 | for (const auto &version : hal.versionRanges) { |
| 348 | appendChild(root, versionRangeConverter(version, d)); |
| 349 | } |
| 350 | } |
| 351 | bool buildObject(MatrixHal *object, NodeType *root) const override { |
Yifan Hong | a70b274 | 2017-02-16 17:43:04 -0800 | [diff] [blame] | 352 | if (!parseAttr(root, "format", &object->format) || |
| 353 | !parseAttr(root, "optional", &object->optional) || |
| 354 | !parseTextElement(root, "name", &object->name) || |
| 355 | !parseChildren(root, versionRangeConverter, &object->versionRanges)) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 356 | return false; |
| 357 | } |
| 358 | return true; |
| 359 | } |
| 360 | }; |
| 361 | |
| 362 | const MatrixHalConverter matrixHalConverter{}; |
| 363 | const XmlConverter<MatrixHal> &gMatrixHalConverter = matrixHalConverter; |
| 364 | |
Yifan Hong | a999357 | 2017-01-24 19:33:15 -0800 | [diff] [blame] | 365 | struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 366 | std::string elementName() const override { return "kernel"; } |
| 367 | void mutateNode(const MatrixKernel &kernel, NodeType *root, DocType *d) const override { |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 368 | appendAttr(root, "version", Version{kernel.mMinLts.version, kernel.mMinLts.majorRev}); |
| 369 | appendAttr(root, "minlts", kernel.mMinLts); |
| 370 | for (const KernelConfig &config : kernel.mConfigs) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 371 | appendChild(root, kernelConfigConverter(config, d)); |
| 372 | } |
| 373 | } |
| 374 | bool buildObject(MatrixKernel *object, NodeType *root) const override { |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 375 | Version v; |
Yifan Hong | a70b274 | 2017-02-16 17:43:04 -0800 | [diff] [blame] | 376 | if (!parseAttr(root, "minlts", &object->mMinLts) || |
| 377 | !parseAttr(root, "version", &v) || |
| 378 | !parseChildren(root, kernelConfigConverter, &object->mConfigs)) { |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 379 | return false; |
| 380 | } |
| 381 | if (v != Version{object->mMinLts.version, object->mMinLts.majorRev}) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 382 | return false; |
| 383 | } |
| 384 | return true; |
| 385 | } |
| 386 | }; |
| 387 | |
| 388 | const MatrixKernelConverter matrixKernelConverter{}; |
| 389 | const XmlConverter<MatrixKernel> &gMatrixKernelConverter = matrixKernelConverter; |
| 390 | |
Yifan Hong | a999357 | 2017-01-24 19:33:15 -0800 | [diff] [blame] | 391 | struct HalImplementationConverter : public XmlNodeConverter<HalImplementation> { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 392 | std::string elementName() const override { return "impl"; } |
| 393 | void mutateNode(const HalImplementation &impl, NodeType *root, DocType *d) const override { |
| 394 | appendAttr(root, "level", impl.implLevel); |
| 395 | appendText(root, impl.impl, d); |
| 396 | } |
| 397 | bool buildObject(HalImplementation *object, NodeType *root) const override { |
Yifan Hong | a70b274 | 2017-02-16 17:43:04 -0800 | [diff] [blame] | 398 | if (!parseAttr(root, "level", &object->implLevel) || |
| 399 | !parseText(root, &object->impl)) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 400 | return false; |
| 401 | } |
| 402 | return true; |
| 403 | } |
| 404 | }; |
| 405 | |
| 406 | const HalImplementationConverter halImplementationConverter{}; |
| 407 | const XmlConverter<HalImplementation> &gHalImplementationConverter = halImplementationConverter; |
| 408 | |
Yifan Hong | a999357 | 2017-01-24 19:33:15 -0800 | [diff] [blame] | 409 | struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 410 | std::string elementName() const override { return "hal"; } |
| 411 | void mutateNode(const ManifestHal &hal, NodeType *root, DocType *d) const override { |
| 412 | appendAttr(root, "format", hal.format); |
| 413 | appendTextElement(root, "name", hal.name, d); |
| 414 | appendChild(root, transportConverter(hal.transport, d)); |
| 415 | appendChild(root, |
| 416 | halImplementationConverter(hal.impl, d)); |
| 417 | for (const auto &version : hal.versions) { |
| 418 | appendChild(root, versionConverter(version, d)); |
| 419 | } |
| 420 | } |
| 421 | bool buildObject(ManifestHal *object, NodeType *root) const override { |
Yifan Hong | a70b274 | 2017-02-16 17:43:04 -0800 | [diff] [blame] | 422 | if (!parseAttr(root, "format", &object->format) || |
| 423 | !parseTextElement(root, "name", &object->name) || |
| 424 | !parseChild(root, transportConverter, &object->transport) || |
| 425 | !parseChild(root, halImplementationConverter, &object->impl) || |
| 426 | !parseChildren(root, versionConverter, &object->versions)) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 427 | return false; |
| 428 | } |
Yifan Hong | 5a06ef7 | 2017-01-24 19:54:24 -0800 | [diff] [blame] | 429 | return object->isValid(); |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 430 | } |
| 431 | }; |
| 432 | |
| 433 | const ManifestHalConverter manifestHalConverter{}; |
| 434 | const XmlConverter<ManifestHal> &gManifestHalConverter = manifestHalConverter; |
| 435 | |
Yifan Hong | 558380a | 2017-02-09 15:37:32 -0800 | [diff] [blame] | 436 | const XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"}; |
| 437 | const XmlTextConverter<SepolicyVersion> sepolicyVersionConverter{"sepolicy-version"}; |
| 438 | |
Yifan Hong | a999357 | 2017-01-24 19:33:15 -0800 | [diff] [blame] | 439 | struct SepolicyConverter : public XmlNodeConverter<Sepolicy> { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 440 | std::string elementName() const override { return "sepolicy"; } |
Yifan Hong | 558380a | 2017-02-09 15:37:32 -0800 | [diff] [blame] | 441 | void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override { |
| 442 | appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d)); |
| 443 | appendChild(root, sepolicyVersionConverter(object.sepolicyVersion(), d)); |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 444 | } |
Yifan Hong | 558380a | 2017-02-09 15:37:32 -0800 | [diff] [blame] | 445 | bool buildObject(Sepolicy *object, NodeType *root) const override { |
| 446 | if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion) || |
| 447 | !parseChild(root, sepolicyVersionConverter, &object->mSepolicyVersion)) { |
| 448 | return false; |
| 449 | } |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 450 | return true; |
| 451 | } |
| 452 | }; |
| 453 | const SepolicyConverter sepolicyConverter{}; |
| 454 | const XmlConverter<Sepolicy> &gSepolicyConverter = sepolicyConverter; |
| 455 | |
Yifan Hong | a999357 | 2017-01-24 19:33:15 -0800 | [diff] [blame] | 456 | struct VendorManifestConverter : public XmlNodeConverter<VendorManifest> { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 457 | std::string elementName() const override { return "manifest"; } |
| 458 | void mutateNode(const VendorManifest &m, NodeType *root, DocType *d) const override { |
| 459 | appendAttr(root, "version", VendorManifest::kVersion); |
Yifan Hong | ef6d4d3 | 2017-01-23 14:12:28 -0800 | [diff] [blame] | 460 | for (const auto &hal : m.getHals()) { |
| 461 | appendChild(root, manifestHalConverter(hal, d)); |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 462 | } |
| 463 | } |
| 464 | bool buildObject(VendorManifest *object, NodeType *root) const override { |
| 465 | std::vector<ManifestHal> hals; |
| 466 | if (!parseChildren(root, manifestHalConverter, &hals)) { |
| 467 | return false; |
| 468 | } |
| 469 | for (auto &&hal : hals) { |
| 470 | object->add(std::move(hal)); |
| 471 | } |
| 472 | return true; |
| 473 | } |
| 474 | }; |
| 475 | |
| 476 | const VendorManifestConverter vendorManifestConverter{}; |
| 477 | const XmlConverter<VendorManifest> &gVendorManifestConverter = vendorManifestConverter; |
| 478 | |
Yifan Hong | a999357 | 2017-01-24 19:33:15 -0800 | [diff] [blame] | 479 | struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 480 | std::string elementName() const override { return "compatibility-matrix"; } |
| 481 | void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override { |
| 482 | appendAttr(root, "version", CompatibilityMatrix::kVersion); |
Yifan Hong | ec34286 | 2017-02-16 17:57:06 -0800 | [diff] [blame^] | 483 | for (const auto &pair : m.mHals) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 484 | appendChild(root, matrixHalConverter(pair.second, d)); |
| 485 | } |
Yifan Hong | ec34286 | 2017-02-16 17:57:06 -0800 | [diff] [blame^] | 486 | for (const auto &kernel : m.mKernels) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 487 | appendChild(root, matrixKernelConverter(kernel, d)); |
| 488 | } |
Yifan Hong | ec34286 | 2017-02-16 17:57:06 -0800 | [diff] [blame^] | 489 | appendChild(root, sepolicyConverter(m.mSepolicy, d)); |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 490 | } |
| 491 | bool buildObject(CompatibilityMatrix *object, NodeType *root) const override { |
| 492 | std::vector<MatrixHal> hals; |
Yifan Hong | a70b274 | 2017-02-16 17:43:04 -0800 | [diff] [blame] | 493 | if (!parseChildren(root, matrixHalConverter, &hals) || |
Yifan Hong | ec34286 | 2017-02-16 17:57:06 -0800 | [diff] [blame^] | 494 | !parseChildren(root, matrixKernelConverter, &object->mKernels) || |
| 495 | !parseChild(root, sepolicyConverter, &object->mSepolicy)) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 496 | return false; |
| 497 | } |
| 498 | for (auto &&hal : hals) { |
| 499 | object->add(std::move(hal)); |
| 500 | } |
| 501 | return true; |
| 502 | } |
| 503 | }; |
| 504 | |
| 505 | const CompatibilityMatrixConverter compatibilityMatrixConverter{}; |
| 506 | const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter |
| 507 | = compatibilityMatrixConverter; |
| 508 | |
| 509 | } // namespace vintf |
| 510 | } // namespace android |