1676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong/*
2676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * Copyright (C) 2017 The Android Open Source Project
3676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong *
4676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * Licensed under the Apache License, Version 2.0 (the "License");
5676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * you may not use this file except in compliance with the License.
6676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * You may obtain a copy of the License at
7676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong *
8676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong *      http://www.apache.org/licenses/LICENSE-2.0
9676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong *
10676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * Unless required by applicable law or agreed to in writing, software
11676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * distributed under the License is distributed on an "AS IS" BASIS,
12676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * See the License for the specific language governing permissions and
14676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong * limitations under the License.
15676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong */
16676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
17676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// Convert objects from and to xml.
18676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
19676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong#include <tinyxml2.h>
20676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
21676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong#include "parse_string.h"
22676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong#include "parse_xml.h"
23676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
24676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongnamespace android {
25676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongnamespace vintf {
26676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
27676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// --------------- tinyxml2 details
28676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
29676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongusing NodeType = tinyxml2::XMLElement;
30676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongusing DocType = tinyxml2::XMLDocument;
31676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
32676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// caller is responsible for deleteDocument() call
33676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline DocType *createDocument() {
34676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return new tinyxml2::XMLDocument();
35676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
36676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
37676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// caller is responsible for deleteDocument() call
38676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline DocType *createDocument(const std::string &xml) {
39676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    DocType *doc = new tinyxml2::XMLDocument();
40676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    if (doc->Parse(xml.c_str()) == tinyxml2::XML_NO_ERROR) {
41676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return doc;
42676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
43676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    delete doc;
44676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return nullptr;
45676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
46676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
47676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline void deleteDocument(DocType *d) {
48676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    delete d;
49676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
50676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
51676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline std::string printDocument(DocType *d) {
52676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    tinyxml2::XMLPrinter p;
53676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    d->Print(&p);
54676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return std::string{p.CStr()};
55676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
56676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
57676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline NodeType *createNode(const std::string &name, DocType *d) {
58676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return d->NewElement(name.c_str());
59676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
60676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
61676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline void appendChild(NodeType *parent, NodeType *child) {
62676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    parent->InsertEndChild(child);
63676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
64676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
65676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline void appendChild(DocType *parent, NodeType *child) {
66676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    parent->InsertEndChild(child);
67676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
68676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
69676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
70676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    e->SetAttribute(attrName.c_str(), attr.c_str());
71676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
72676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
73676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// text -> text
74676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline void appendText(NodeType *parent, const std::string &text, DocType *d) {
75676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    parent->InsertEndChild(d->NewText(text.c_str()));
76676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
77676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
78676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline std::string nameOf(NodeType *root) {
79cd41ffc75e885e2b407e4eff3d761d59ffa0d766Yifan Hong    return root->Name() == NULL ? "" : root->Name();
80676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
81676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
82676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline std::string getText(NodeType *root) {
83cd41ffc75e885e2b407e4eff3d761d59ffa0d766Yifan Hong    return root->GetText() == NULL ? "" : root->GetText();
84676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
85676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
86676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline NodeType *getChild(NodeType *parent, const std::string &name) {
87676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return parent->FirstChildElement(name.c_str());
88676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
89676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
90676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline NodeType *getRootChild(DocType *parent) {
91676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return parent->FirstChildElement();
92676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
93676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
94676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
95676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::vector<NodeType *> v;
96676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    for (NodeType *child = parent->FirstChildElement(name.c_str());
97676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong         child != nullptr;
98676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong         child = child->NextSiblingElement(name.c_str())) {
99676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        v.push_back(child);
100676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
101676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return v;
102676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
103676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
104676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Honginline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
105676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    const char *c = root->Attribute(attrName.c_str());
106676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    if (c == NULL)
107676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return false;
108676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    *s = c;
109676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    return true;
110676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong}
111676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
112676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// --------------- tinyxml2 details end.
113676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
1148e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong// Helper functions for XmlConverter
1158e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hongstatic bool parse(const std::string &attrText, bool *attr) {
1168e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    if (attrText == "true" || attrText == "1") {
1178e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        *attr = true;
1188e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        return true;
1198e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    }
1208e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    if (attrText == "false" || attrText == "0") {
1218e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        *attr = false;
1228e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        return true;
1238e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    }
1248e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    return false;
1258e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong}
1268e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong
127676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// ---------------------- XmlNodeConverter definitions
128676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
129676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongtemplate<typename Object>
130676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongstruct XmlNodeConverter : public XmlConverter<Object> {
131676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    XmlNodeConverter() {}
132676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    virtual ~XmlNodeConverter() {}
133676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
134676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    // sub-types should implement these.
135676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
136676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    virtual bool buildObject(Object *o, NodeType *n) const = 0;
137676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    virtual std::string elementName() const = 0;
138676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
139676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    // convenience methods for user
140676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline const std::string &lastError() const { return mLastError; }
141676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline NodeType *serialize(const Object &o, DocType *d) const {
142676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        NodeType *root = createNode(this->elementName(), d);
143676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        this->mutateNode(o, root, d);
144676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return root;
145676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
146676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline std::string serialize(const Object &o) const {
147676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        DocType *doc = createDocument();
148676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendChild(doc, serialize(o, doc));
149676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        std::string s = printDocument(doc);
150676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        deleteDocument(doc);
151676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return s;
152676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
153676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool deserialize(Object *object, NodeType *root) const {
154676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        if (nameOf(root) != this->elementName()) {
155676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            return false;
156676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
157676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return this->buildObject(object, root);
158676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
159676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool deserialize(Object *o, const std::string &xml) const {
160676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        DocType *doc = createDocument(xml);
161685ce898962e83f09c0b7eaf079a6542b71e7f3dYifan Hong        if (doc == nullptr) {
162685ce898962e83f09c0b7eaf079a6542b71e7f3dYifan Hong            this->mLastError = "Not a valid XML";
163685ce898962e83f09c0b7eaf079a6542b71e7f3dYifan Hong            return false;
164685ce898962e83f09c0b7eaf079a6542b71e7f3dYifan Hong        }
165685ce898962e83f09c0b7eaf079a6542b71e7f3dYifan Hong        bool ret = deserialize(o, getRootChild(doc));
166676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        deleteDocument(doc);
167676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return ret;
168676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
169676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline NodeType *operator()(const Object &o, DocType *d) const {
170676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return serialize(o, d);
171676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
172676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline std::string operator()(const Object &o) const {
173676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return serialize(o);
174676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
175676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool operator()(Object *o, NodeType *node) const {
176676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return deserialize(o, node);
177676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
178676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool operator()(Object *o, const std::string &xml) const {
179676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return deserialize(o, xml);
180676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
181676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
182676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    // convenience methods for implementor.
1838e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong
1848e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    // All append* functions helps mutateNode() to serialize the object into XML.
185676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    template <typename T>
186676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
187676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
188676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
189676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
190676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
191676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return appendStrAttr(e, attrName, attr ? "true" : "false");
192676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
193676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
19433466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    // text -> <name>text</name>
19533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    inline void appendTextElement(NodeType *parent, const std::string &name,
19633466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong                const std::string &text, DocType *d) const {
19733466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        NodeType *c = createNode(name, d);
19833466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        appendText(c, text, d);
19933466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        appendChild(parent, c);
20033466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    }
20133466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong
20233466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    // text -> <name>text</name>
20333466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    template<typename Array>
20433466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    inline void appendTextElements(NodeType *parent, const std::string &name,
20533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong                const Array &array, DocType *d) const {
20633466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        for (const std::string &text : array) {
20733466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            NodeType *c = createNode(name, d);
20833466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            appendText(c, text, d);
20933466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            appendChild(parent, c);
21033466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        }
21133466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    }
21233466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong
21333466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    template<typename T, typename Array>
21433466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    inline void appendChildren(NodeType *parent, const XmlNodeConverter<T> &conv,
21533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            const Array &array, DocType *d) const {
21633466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        for (const T &t : array) {
21733466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            appendChild(parent, conv(t, d));
21833466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        }
21933466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    }
22033466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong
2218e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    // All parse* functions helps buildObject() to deserialize XML to the object. Returns
2228e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    // true if deserialization is successful, false if any error, and mLastError will be
2238e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    // set to error message.
2248e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    template <typename T>
2258e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    inline bool parseOptionalAttr(NodeType *root, const std::string &attrName,
2268e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong            T &&defaultValue, T *attr) const {
2278e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        std::string attrText;
2288e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        bool success = getAttr(root, attrName, &attrText) &&
2298e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong                       ::android::vintf::parse(attrText, attr);
2308e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        if (!success) {
2318e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong            *attr = std::move(defaultValue);
2328e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        }
2338e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        return true;
2348e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    }
2358e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong
236676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    template <typename T>
237676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool parseAttr(NodeType *root, const std::string &attrName, T *attr) const {
238676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        std::string attrText;
239676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
240676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        if (!ret) {
2416dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong            mLastError = "Could not find/parse attr with name \"" + attrName + "\" for element <"
2426dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong                    + elementName() + ">";
243676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
244676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return ret;
245676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
246676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
247676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool parseAttr(NodeType *root, const std::string &attrName, std::string *attr) const {
248676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        bool ret = getAttr(root, attrName, attr);
249676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        if (!ret) {
2506dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong            mLastError = "Could not find attr with name \"" + attrName + "\" for element <"
2516dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong                    + elementName() + ">";
252676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
253676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return ret;
254676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
255676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
256676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool parseTextElement(NodeType *root,
257676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            const std::string &elementName, std::string *s) const {
258676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        NodeType *child = getChild(root, elementName);
259676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        if (child == nullptr) {
2606dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong            mLastError = "Could not find element with name <" + elementName + "> in element <"
2616dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong                    + this->elementName() + ">";
262676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            return false;
263676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
264676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        *s = getText(child);
265676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
266676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
267676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
26833466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    inline bool parseTextElements(NodeType *root, const std::string &elementName,
26933466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            std::vector<std::string> *v) const {
27033466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        auto nodes = getChildren(root, elementName);
27133466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        v->resize(nodes.size());
27233466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        for (size_t i = 0; i < nodes.size(); ++i) {
27333466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            v->at(i) = getText(nodes[i]);
27433466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        }
27533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        return true;
27633466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong    }
27733466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong
278676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    template <typename T>
279676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool parseChild(NodeType *root, const XmlNodeConverter<T> &conv, T *t) const {
280676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        NodeType *child = getChild(root, conv.elementName());
281676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        if (child == nullptr) {
2826dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong            mLastError = "Could not find element with name <" + conv.elementName() + "> in element <"
2836dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong                    + this->elementName() + ">";
284676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            return false;
285676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
286676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        bool success = conv.deserialize(t, child);
287676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        if (!success) {
288676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            mLastError = conv.lastError();
289676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
290676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return success;
291676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
292676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
293676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    template <typename T>
2948e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    inline bool parseOptionalChild(NodeType *root, const XmlNodeConverter<T> &conv,
2958e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong            T &&defaultValue, T *t) const {
2968e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        NodeType *child = getChild(root, conv.elementName());
2978e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        if (child == nullptr) {
2988e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong            *t = std::move(defaultValue);
2998e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong            return true;
3008e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        }
3018e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        bool success = conv.deserialize(t, child);
3028e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        if (!success) {
3038e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong            mLastError = conv.lastError();
3048e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        }
3058e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        return success;
3068e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    }
3078e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong
3088e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong    template <typename T>
309676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::vector<T> *v) const {
310676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        auto nodes = getChildren(root, conv.elementName());
311676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        v->resize(nodes.size());
312676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        for (size_t i = 0; i < nodes.size(); ++i) {
313676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            if (!conv.deserialize(&v->at(i), nodes[i])) {
3146dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong                mLastError = "Could not parse element with name <" + conv.elementName()
3156dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong                        + "> in element <" + this->elementName() + ">: " + conv.lastError();
316676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong                return false;
317676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            }
318676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
319676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
320676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
321676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
32257b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    template <typename T>
32357b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::set<T> *s) const {
32457b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        std::vector<T> vec;
32557b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        if (!parseChildren(root, conv, &vec)) {
32657b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            return false;
32757b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        }
32857b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        s->clear();
32957b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        s->insert(vec.begin(), vec.end());
33057b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        if (s->size() != vec.size()) {
33157b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            mLastError = "Duplicated elements <" + conv.elementName() + "> in element <"
33257b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                    + this->elementName() + ">";
33357b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            s->clear();
33457b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            return false;
33557b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        }
33657b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        return true;
33757b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    }
33857b7f0c0360b2603e348ffa5892438754041a95dYifan Hong
339676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    inline bool parseText(NodeType *node, std::string *s) const {
340676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        *s = getText(node);
341676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
342676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
343676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
344c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    template <typename T>
345c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    inline bool parseText(NodeType *node, T *s) const {
3466dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong        std::string text = getText(node);
3476dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong        bool ret = ::android::vintf::parse(text, s);
3486dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong        if (!ret) {
3496dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong            mLastError = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
3506dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong        }
3516dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong        return ret;
352c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    }
353676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongprotected:
354676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    mutable std::string mLastError;
355676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
356676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
357676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongtemplate<typename Object>
358676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongstruct XmlTextConverter : public XmlNodeConverter<Object> {
359676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    XmlTextConverter(const std::string &elementName)
360676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        : mElementName(elementName) {}
361676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
362676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
363676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendText(root, ::android::vintf::to_string(object), d);
364676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
365676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    virtual bool buildObject(Object *object, NodeType *root) const override {
3666dbf63f40e00dfd74639c84a3ed4c9284a3ab2c7Yifan Hong        return this->parseText(root, object);
367676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
368676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    virtual std::string elementName() const { return mElementName; };
369676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongprivate:
370676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::string mElementName;
371676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
372676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
373676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong// ---------------------- XmlNodeConverter definitions end
374676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
375676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst XmlTextConverter<Version> versionConverter{"version"};
376676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
377676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst XmlTextConverter<VersionRange> versionRangeConverter{"version"};
378676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
3793f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hongconst XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
3803f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong
381c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hongstruct TransportArchConverter : public XmlNodeConverter<TransportArch> {
382c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    std::string elementName() const override { return "transport"; }
383c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
384c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        if (object.arch != Arch::ARCH_EMPTY) {
385c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            appendAttr(root, "arch", object.arch);
386c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        }
387c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        appendText(root, ::android::vintf::to_string(object.transport), d);
388c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    }
389c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    bool buildObject(TransportArch *object, NodeType *root) const override {
390c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch) ||
391c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            !parseText(root, &object->transport)) {
392c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            return false;
393c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        }
394c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        if (!object->isValid()) {
395c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            this->mLastError = "transport == " + ::android::vintf::to_string(object->transport) +
396c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong                    " and arch == " + ::android::vintf::to_string(object->arch) +
397c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong                    " is not a valid combination.";
398c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            return false;
399c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        }
400c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        return true;
401c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong    }
402c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong};
403c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong
404c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hongconst TransportArchConverter transportArchConverter{};
405c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong
4063f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hongstruct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
4073f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    std::string elementName() const override { return "value"; }
4083f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
4093f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        appendAttr(root, "type", object.mType);
4103f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        appendText(root, ::android::vintf::to_string(object), d);
4113f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    }
4123f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override {
4133f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        std::string stringValue;
4143f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        if (!parseAttr(root, "type", &object->mType) ||
4153f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong            !parseText(root, &stringValue)) {
4163f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong            return false;
4173f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        }
4183f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
41933466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            this->mLastError = "Could not parse kernel config value \"" + stringValue + "\"";
4203f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong            return false;
4213f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        }
4223f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        return true;
4233f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    }
4243f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong};
4253f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong
4263f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hongconst KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
4273f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong
4283f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hongstruct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
4293f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    std::string elementName() const override { return "config"; }
4303f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    void mutateNode(const KernelConfig &object, NodeType *root, DocType *d) const override {
4313f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        appendChild(root, kernelConfigKeyConverter(object.first, d));
4323f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        appendChild(root, kernelConfigTypedValueConverter(object.second, d));
4333f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    }
4343f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    bool buildObject(KernelConfig *object, NodeType *root) const override {
4353f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        if (   !parseChild(root, kernelConfigKeyConverter, &object->first)
4363f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong            || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) {
4373f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong            return false;
4383f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        }
4393f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        return true;
4403f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong    }
4413f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong};
4423f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong
4433f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hongconst KernelConfigConverter kernelConfigConverter{};
4443f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong
44596d4649f72786806e4c385817d05a2b921c2f4ecYifan Hongstruct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
44696d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong    std::string elementName() const override { return "interface"; }
44796d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong    void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
44896d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        appendTextElement(root, "name", intf.name, d);
44996d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        appendTextElements(root, "instance", intf.instances, d);
45096d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong    }
45196d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong    bool buildObject(HalInterface *intf, NodeType *root) const override {
45296d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        std::vector<std::string> instances;
45396d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        if (!parseTextElement(root, "name", &intf->name) ||
45496d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong            !parseTextElements(root, "instance", &instances)) {
45596d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong            return false;
45696d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        }
45796d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        intf->instances.clear();
45896d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        intf->instances.insert(instances.begin(), instances.end());
45996d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        if (intf->instances.size() != instances.size()) {
46096d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong            this->mLastError = "Duplicated instances in " + intf->name;
46196d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong            return false;
46296d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        }
46396d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        return true;
46496d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong    }
46596d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong};
46696d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong
46796d4649f72786806e4c385817d05a2b921c2f4ecYifan Hongconst HalInterfaceConverter halInterfaceConverter{};
46896d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong
469a9993574bc1fb7a99ebf05cdc69d99cd208b8cf5Yifan Hongstruct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
470676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::string elementName() const override { return "hal"; }
471676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
472676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendAttr(root, "format", hal.format);
473676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendAttr(root, "optional", hal.optional);
474676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendTextElement(root, "name", hal.name, d);
47533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        appendChildren(root, versionRangeConverter, hal.versionRanges, d);
47643e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong        appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
477676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
478676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    bool buildObject(MatrixHal *object, NodeType *root) const override {
47943e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong        std::vector<HalInterface> interfaces;
4808e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
4818e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong            !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional) ||
482a70b274227269d2e924a6f570015879c7c9f8f86Yifan Hong            !parseTextElement(root, "name", &object->name) ||
48343e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong            !parseChildren(root, versionRangeConverter, &object->versionRanges) ||
48443e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong            !parseChildren(root, halInterfaceConverter, &interfaces)) {
485676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            return false;
486676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
48743e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong        for (auto&& interface : interfaces) {
48843e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong            std::string name{interface.name};
48943e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong            auto res = object->interfaces.emplace(std::move(name), std::move(interface));
49043e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong            if (!res.second) {
49143e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong                this->mLastError = "Duplicated instance entry " + res.first->first;
49243e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong                return false;
49343e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong            }
49443e2aaeb4b857cc7a2f55e6aeb5f8ec9bcc63c7dYifan Hong        }
495676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
496676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
497676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
498676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
499676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst MatrixHalConverter matrixHalConverter{};
500676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
501a9993574bc1fb7a99ebf05cdc69d99cd208b8cf5Yifan Hongstruct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
502676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::string elementName() const override { return "kernel"; }
503676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    void mutateNode(const MatrixKernel &kernel, NodeType *root, DocType *d) const override {
504c3066898a725859cc2a6d4c0d3dce88284807e76Yifan Hong        appendAttr(root, "version", kernel.mMinLts);
50533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        appendChildren(root, kernelConfigConverter, kernel.mConfigs, d);
506676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
507676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    bool buildObject(MatrixKernel *object, NodeType *root) const override {
508c3066898a725859cc2a6d4c0d3dce88284807e76Yifan Hong        if (!parseAttr(root, "version", &object->mMinLts) ||
509a70b274227269d2e924a6f570015879c7c9f8f86Yifan Hong            !parseChildren(root, kernelConfigConverter, &object->mConfigs)) {
5103f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong            return false;
5113f5489a519f5f1a7eb8bd7873a3170057502d93bYifan Hong        }
512676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
513676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
514676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
515676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
516676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst MatrixKernelConverter matrixKernelConverter{};
517676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
518a9993574bc1fb7a99ebf05cdc69d99cd208b8cf5Yifan Hongstruct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
519676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::string elementName() const override { return "hal"; }
520676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    void mutateNode(const ManifestHal &hal, NodeType *root, DocType *d) const override {
521676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendAttr(root, "format", hal.format);
522676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendTextElement(root, "name", hal.name, d);
523c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        if (!hal.transportArch.empty()) {
524c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            appendChild(root, transportArchConverter(hal.transportArch, d));
525c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        }
52633466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        appendChildren(root, versionConverter, hal.versions, d);
52796d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
528676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
529676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    bool buildObject(ManifestHal *object, NodeType *root) const override {
53096d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong        std::vector<HalInterface> interfaces;
5318e9c669c47a9b59bc49d5c95922c17f1d75a6620Yifan Hong        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
532a70b274227269d2e924a6f570015879c7c9f8f86Yifan Hong            !parseTextElement(root, "name", &object->name) ||
533c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            !parseChild(root, transportArchConverter, &object->transportArch) ||
534ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong            !parseChildren(root, versionConverter, &object->versions) ||
53596d4649f72786806e4c385817d05a2b921c2f4ecYifan Hong            !parseChildren(root, halInterfaceConverter, &interfaces)) {
536676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            return false;
537676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
538ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong        object->interfaces.clear();
539ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong        for (auto &&interface : interfaces) {
540ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong            auto res = object->interfaces.emplace(interface.name,
541ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong                                                  std::move(interface));
542ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong            if (!res.second) {
543ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong                this->mLastError = "Duplicated instance entry " + res.first->first;
544ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong                return false;
545ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong            }
546ec3b9b7cf729c8cc47421dcc316d7b2d1f37c2ffYifan Hong        }
547c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        if (!object->isValid()) {
548c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            this->mLastError = "'" + object->name + "' is not a valid Manifest HAL.";
549c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong            return false;
550c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        }
551c54d32cb0b20308a0ecea7864016a2a5dc512f71Yifan Hong        return true;
552676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
553676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
554676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
5554a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hong// Convert ManifestHal from and to XML. Returned object is guaranteed to have
5564a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hong// .isValid() == true.
557676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst ManifestHalConverter manifestHalConverter{};
558676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
559558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hongconst XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
5603916619e525f6aed4a3ef93881452157ce12d76eYifan Hongconst XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
561558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hong
562a9993574bc1fb7a99ebf05cdc69d99cd208b8cf5Yifan Hongstruct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
563676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::string elementName() const override { return "sepolicy"; }
564558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hong    void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
565558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hong        appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
5663916619e525f6aed4a3ef93881452157ce12d76eYifan Hong        appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
567676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
568558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hong    bool buildObject(Sepolicy *object, NodeType *root) const override {
569558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hong        if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion) ||
5703916619e525f6aed4a3ef93881452157ce12d76eYifan Hong            !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges)) {
571558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hong            return false;
572558380a7b95de37f6c74de683102f78e97e4fbf0Yifan Hong        }
573676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
574676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
575676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
576676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst SepolicyConverter sepolicyConverter{};
577676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
57857b7f0c0360b2603e348ffa5892438754041a95dYifan Hongconst XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
57957b7f0c0360b2603e348ffa5892438754041a95dYifan Hongconst XmlTextConverter<std::string> vndkLibraryConverter{"library"};
58057b7f0c0360b2603e348ffa5892438754041a95dYifan Hong
58157b7f0c0360b2603e348ffa5892438754041a95dYifan Hongstruct VndkConverter : public XmlNodeConverter<Vndk> {
58257b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    std::string elementName() const override { return "vndk"; }
58357b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
58457b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
58557b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
58657b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    }
58757b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    bool buildObject(Vndk *object, NodeType *root) const override {
58857b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange) ||
58957b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) {
59057b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            return false;
59157b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        }
59257b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        return true;
59357b7f0c0360b2603e348ffa5892438754041a95dYifan Hong    }
59457b7f0c0360b2603e348ffa5892438754041a95dYifan Hong};
59557b7f0c0360b2603e348ffa5892438754041a95dYifan Hong
59657b7f0c0360b2603e348ffa5892438754041a95dYifan Hongconst VndkConverter vndkConverter{};
59757b7f0c0360b2603e348ffa5892438754041a95dYifan Hong
598d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hongstruct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
599d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong    std::string elementName() const override { return "sepolicy"; }
600d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong    void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
601d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong        appendChild(root, versionConverter(m, d));
602d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong    }
603d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong    bool buildObject(Version *object, NodeType *root) const override {
604d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong        return parseChild(root, versionConverter, object);
605d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong    }
606d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong};
607d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hongconst HalManifestSepolicyConverter halManifestSepolicyConverter{};
608d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong
609d2b7e64894cd739da60f129ac38d0cf035238206Yifan Hongstruct HalManifestConverter : public XmlNodeConverter<HalManifest> {
610676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::string elementName() const override { return "manifest"; }
611d2b7e64894cd739da60f129ac38d0cf035238206Yifan Hong    void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
612d2b7e64894cd739da60f129ac38d0cf035238206Yifan Hong        appendAttr(root, "version", HalManifest::kVersion);
613f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        appendAttr(root, "type", m.mType);
61433466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        appendChildren(root, manifestHalConverter, m.getHals(), d);
615d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong        if (m.mType == SchemaType::DEVICE) {
616d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong            appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
61757b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        } else if (m.mType == SchemaType::FRAMEWORK) {
61857b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            appendChildren(root, vndkConverter, m.framework.mVndks, d);
619d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong        }
620676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
621d2b7e64894cd739da60f129ac38d0cf035238206Yifan Hong    bool buildObject(HalManifest *object, NodeType *root) const override {
622f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        Version version;
623676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        std::vector<ManifestHal> hals;
624f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        if (!parseAttr(root, "version", &version) ||
625f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            !parseAttr(root, "type", &object->mType) ||
626f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            !parseChildren(root, manifestHalConverter, &hals)) {
627f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            return false;
628f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        }
629f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        if (version != HalManifest::kVersion) {
630f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            this->mLastError = "Unrecognized manifest.version";
631676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            return false;
632676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
633d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong        if (object->mType == SchemaType::DEVICE) {
634d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong            // tags for device hal manifest only.
635d73ef5d7f1b48adf07a9b09c4ef89ba79f5fa166Yifan Hong            // <sepolicy> can be missing because it can be determined at build time, not hard-coded
636d73ef5d7f1b48adf07a9b09c4ef89ba79f5fa166Yifan Hong            // in the XML file.
637d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong            if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
638d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong                    &object->device.mSepolicyVersion)) {
639d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong                return false;
640d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong            }
64157b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        } else if (object->mType == SchemaType::FRAMEWORK) {
64257b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) {
64357b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                return false;
64457b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            }
64557b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            for (const auto &vndk : object->framework.mVndks) {
64657b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                if (!vndk.mVersionRange.isSingleVersion()) {
64757b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                    this->mLastError = "vndk.version " + to_string(vndk.mVersionRange)
64857b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                            + " cannot be a range for manifests";
64957b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                    return false;
65057b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                }
65157b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            }
652d19539c0858b168e6417a7eb88c1f47a388652f2Yifan Hong        }
653676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        for (auto &&hal : hals) {
65413d12186a0c49a10bff1dc47c3fe0437fcfa1f67Yifan Hong            std::string description{hal.name};
65533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            if (!object->add(std::move(hal))) {
65613d12186a0c49a10bff1dc47c3fe0437fcfa1f67Yifan Hong                this->mLastError = "Duplicated manifest.hal entry " + description;
65733466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong                return false;
65833466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            }
659676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
660676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
661676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
662676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
663676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
664d2b7e64894cd739da60f129ac38d0cf035238206Yifan Hongconst HalManifestConverter halManifestConverter{};
665676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
666dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hongconst XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
667dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hongstruct AvbConverter : public XmlNodeConverter<Version> {
668dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong    std::string elementName() const override { return "avb"; }
669dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong    void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
670dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong        appendChild(root, avbVersionConverter(m, d));
671dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong    }
672dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong    bool buildObject(Version *object, NodeType *root) const override {
673dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong        return parseChild(root, avbVersionConverter, object);
674dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong    }
675dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong};
676dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hongconst AvbConverter avbConverter{};
677dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong
678a9993574bc1fb7a99ebf05cdc69d99cd208b8cf5Yifan Hongstruct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
679676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    std::string elementName() const override { return "compatibility-matrix"; }
680676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
681676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        appendAttr(root, "version", CompatibilityMatrix::kVersion);
682f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        appendAttr(root, "type", m.mType);
68333466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong        appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
684f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        if (m.mType == SchemaType::FRAMEWORK) {
685f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            appendChildren(root, matrixKernelConverter, m.framework.mKernels, d);
686f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
687dc145b385fc9d369335d8176ff6b504b6c37f219Yifan Hong            appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
688d32fafa76e3b9661dfa81c266a64b8d46f95af20Yifan Hong        } else if (m.mType == SchemaType::DEVICE) {
689d32fafa76e3b9661dfa81c266a64b8d46f95af20Yifan Hong            appendChild(root, vndkConverter(m.device.mVndk, d));
690f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        }
691676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
692676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    bool buildObject(CompatibilityMatrix *object, NodeType *root) const override {
693f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        Version version;
694676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        std::vector<MatrixHal> hals;
695f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        if (!parseAttr(root, "version", &version) ||
696f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            !parseAttr(root, "type", &object->mType) ||
697f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            !parseChildren(root, matrixHalConverter, &hals)) {
698f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            return false;
699f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        }
700f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong
701f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        if (object->mType == SchemaType::FRAMEWORK) {
7022272bf856d9c6a55c7faf81408e0e808664569f3Yifan Hong            // <avb> and <sepolicy> can be missing because it can be determined at build time, not
7032272bf856d9c6a55c7faf81408e0e808664569f3Yifan Hong            // hard-coded in the XML file.
704f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels) ||
7052272bf856d9c6a55c7faf81408e0e808664569f3Yifan Hong                !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy) ||
706a34a71c7176a5e95c71d6934731b7eeb2ff6c573Yifan Hong                !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion)) {
707f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong                return false;
708f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            }
70957b7f0c0360b2603e348ffa5892438754041a95dYifan Hong        } else if (object->mType == SchemaType::DEVICE) {
7103740ba7aafa6e309c3b307ff0c6616335b3ffb61Yifan Hong            // <vndk> can be missing because it can be determined at build time, not hard-coded
7113740ba7aafa6e309c3b307ff0c6616335b3ffb61Yifan Hong            // in the XML file.
7123740ba7aafa6e309c3b307ff0c6616335b3ffb61Yifan Hong            if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) {
71357b7f0c0360b2603e348ffa5892438754041a95dYifan Hong                return false;
71457b7f0c0360b2603e348ffa5892438754041a95dYifan Hong            }
715f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        }
716f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong
717f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong        if (version != CompatibilityMatrix::kVersion) {
718f3a68574718c38ef9445f1cf49104a6130c5b23aYifan Hong            this->mLastError = "Unrecognized compatibility-matrix.version";
719676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong            return false;
720676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
721676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        for (auto &&hal : hals) {
72233466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            if (!object->add(std::move(hal))) {
72333466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong                this->mLastError = "Duplicated compatibility-matrix.hal entry";
72433466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong                return false;
72533466ad37b05f0da75b4b22a2d3f342f60ebfbc6Yifan Hong            }
726676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        }
727676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        return true;
728676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong    }
729676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong};
730676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
731676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst CompatibilityMatrixConverter compatibilityMatrixConverter{};
7324a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hong
7334a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hong// Publicly available as in parse_xml.h
734d2b7e64894cd739da60f129ac38d0cf035238206Yifan Hongconst XmlConverter<HalManifest> &gHalManifestConverter = halManifestConverter;
735676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hongconst XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter
736676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong        = compatibilityMatrixConverter;
737676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong
7384a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hong// For testing in LibVintfTest
7394a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hongconst XmlConverter<Version> &gVersionConverter = versionConverter;
7404a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hongconst XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter
7414a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hong        = kernelConfigTypedValueConverter;
7424a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hongconst XmlConverter<MatrixHal> &gMatrixHalConverter = matrixHalConverter;
743037f12a8b5cabf45a8f69f41e886f017b33ce21eYifan Hongconst XmlConverter<ManifestHal> &gManifestHalConverter = manifestHalConverter;
7444a5eb7ba6b9474aec95c3aa79a606f0b7a6b31b2Yifan Hong
745676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong} // namespace vintf
746676447acd00ebf93d1023f79fc02b5cbbb86dda2Yifan Hong} // namespace android
747