diff options
Diffstat (limited to 'parse_xml.cpp')
-rw-r--r-- | parse_xml.cpp | 444 |
1 files changed, 230 insertions, 214 deletions
diff --git a/parse_xml.cpp b/parse_xml.cpp index 7abbc55..739e344 100644 --- a/parse_xml.cpp +++ b/parse_xml.cpp | |||
@@ -143,50 +143,59 @@ struct XmlNodeConverter : public XmlConverter<Object> { | |||
143 | virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags) const { | 143 | virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags) const { |
144 | mutateNode(o, n, d); | 144 | mutateNode(o, n, d); |
145 | } | 145 | } |
146 | virtual bool buildObject(Object *o, NodeType *n) const = 0; | 146 | virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0; |
147 | virtual std::string elementName() const = 0; | 147 | virtual std::string elementName() const = 0; |
148 | 148 | ||
149 | // convenience methods for user | 149 | // convenience methods for user |
150 | inline const std::string &lastError() const { return mLastError; } | 150 | inline const std::string& lastError() const override { return mLastError; } |
151 | inline NodeType* serialize(const Object& o, DocType* d, | 151 | inline NodeType* serialize(const Object& o, DocType* d, |
152 | SerializeFlags flags = EVERYTHING) const { | 152 | SerializeFlags flags = EVERYTHING) const { |
153 | NodeType *root = createNode(this->elementName(), d); | 153 | NodeType *root = createNode(this->elementName(), d); |
154 | this->mutateNode(o, root, d, flags); | 154 | this->mutateNode(o, root, d, flags); |
155 | return root; | 155 | return root; |
156 | } | 156 | } |
157 | inline std::string serialize(const Object& o, SerializeFlags flags) const { | 157 | inline std::string serialize(const Object& o, SerializeFlags flags) const override { |
158 | DocType *doc = createDocument(); | 158 | DocType *doc = createDocument(); |
159 | appendChild(doc, serialize(o, doc, flags)); | 159 | appendChild(doc, serialize(o, doc, flags)); |
160 | std::string s = printDocument(doc); | 160 | std::string s = printDocument(doc); |
161 | deleteDocument(doc); | 161 | deleteDocument(doc); |
162 | return s; | 162 | return s; |
163 | } | 163 | } |
164 | inline bool deserialize(Object *object, NodeType *root) const { | 164 | inline bool deserialize(Object* object, NodeType* root) { |
165 | bool ret = deserialize(object, root, &mLastError); | ||
166 | return ret; | ||
167 | } | ||
168 | inline bool deserialize(Object* o, const std::string& xml) override { | ||
169 | bool ret = (*this)(o, xml, &mLastError); | ||
170 | return ret; | ||
171 | } | ||
172 | inline bool deserialize(Object* object, NodeType* root, std::string* error) const { | ||
165 | if (nameOf(root) != this->elementName()) { | 173 | if (nameOf(root) != this->elementName()) { |
166 | return false; | 174 | return false; |
167 | } | 175 | } |
168 | return this->buildObject(object, root); | 176 | return this->buildObject(object, root, error); |
169 | } | 177 | } |
170 | inline bool deserialize(Object *o, const std::string &xml) const { | 178 | inline bool operator()(Object* o, const std::string& xml, std::string* error) const override { |
171 | DocType *doc = createDocument(xml); | 179 | std::string errorBuffer; |
180 | if (error == nullptr) error = &errorBuffer; | ||
181 | |||
182 | auto doc = createDocument(xml); | ||
172 | if (doc == nullptr) { | 183 | if (doc == nullptr) { |
173 | this->mLastError = "Not a valid XML"; | 184 | *error = "Not a valid XML"; |
174 | return false; | 185 | return false; |
175 | } | 186 | } |
176 | bool ret = deserialize(o, getRootChild(doc)); | 187 | bool ret = deserialize(o, getRootChild(doc), error); |
177 | deleteDocument(doc); | 188 | deleteDocument(doc); |
178 | return ret; | 189 | return ret; |
179 | } | 190 | } |
180 | inline NodeType *operator()(const Object &o, DocType *d) const { | 191 | inline NodeType *operator()(const Object &o, DocType *d) const { |
181 | return serialize(o, d); | 192 | return serialize(o, d); |
182 | } | 193 | } |
183 | inline std::string operator()(const Object& o, SerializeFlags flags) const { | 194 | inline std::string operator()(const Object& o, SerializeFlags flags) const override { |
184 | return serialize(o, flags); | 195 | return serialize(o, flags); |
185 | } | 196 | } |
186 | inline bool operator()(Object *o, NodeType *node) const { | 197 | inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); } |
187 | return deserialize(o, node); | 198 | inline bool operator()(Object* o, const std::string& xml) override { |
188 | } | ||
189 | inline bool operator()(Object *o, const std::string &xml) const { | ||
190 | return deserialize(o, xml); | 199 | return deserialize(o, xml); |
191 | } | 200 | } |
192 | 201 | ||
@@ -230,11 +239,11 @@ struct XmlNodeConverter : public XmlConverter<Object> { | |||
230 | } | 239 | } |
231 | 240 | ||
232 | // All parse* functions helps buildObject() to deserialize XML to the object. Returns | 241 | // All parse* functions helps buildObject() to deserialize XML to the object. Returns |
233 | // true if deserialization is successful, false if any error, and mLastError will be | 242 | // true if deserialization is successful, false if any error, and "error" will be |
234 | // set to error message. | 243 | // set to error message. |
235 | template <typename T> | 244 | template <typename T> |
236 | inline bool parseOptionalAttr(NodeType *root, const std::string &attrName, | 245 | inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue, |
237 | T &&defaultValue, T *attr) const { | 246 | T* attr, std::string* /* error */) const { |
238 | std::string attrText; | 247 | std::string attrText; |
239 | bool success = getAttr(root, attrName, &attrText) && | 248 | bool success = getAttr(root, attrName, &attrText) && |
240 | ::android::vintf::parse(attrText, attr); | 249 | ::android::vintf::parse(attrText, attr); |
@@ -245,31 +254,33 @@ struct XmlNodeConverter : public XmlConverter<Object> { | |||
245 | } | 254 | } |
246 | 255 | ||
247 | template <typename T> | 256 | template <typename T> |
248 | inline bool parseAttr(NodeType *root, const std::string &attrName, T *attr) const { | 257 | inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr, |
258 | std::string* error) const { | ||
249 | std::string attrText; | 259 | std::string attrText; |
250 | bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr); | 260 | bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr); |
251 | if (!ret) { | 261 | if (!ret) { |
252 | mLastError = "Could not find/parse attr with name \"" + attrName + "\" and value \"" + | 262 | *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" + |
253 | attrText + "\" for element <" + elementName() + ">"; | 263 | attrText + "\" for element <" + elementName() + ">"; |
254 | } | 264 | } |
255 | return ret; | 265 | return ret; |
256 | } | 266 | } |
257 | 267 | ||
258 | inline bool parseAttr(NodeType *root, const std::string &attrName, std::string *attr) const { | 268 | inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr, |
269 | std::string* error) const { | ||
259 | bool ret = getAttr(root, attrName, attr); | 270 | bool ret = getAttr(root, attrName, attr); |
260 | if (!ret) { | 271 | if (!ret) { |
261 | mLastError = "Could not find attr with name \"" + attrName + "\" for element <" | 272 | *error = "Could not find attr with name \"" + attrName + "\" for element <" + |
262 | + elementName() + ">"; | 273 | elementName() + ">"; |
263 | } | 274 | } |
264 | return ret; | 275 | return ret; |
265 | } | 276 | } |
266 | 277 | ||
267 | inline bool parseTextElement(NodeType *root, | 278 | inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s, |
268 | const std::string &elementName, std::string *s) const { | 279 | std::string* error) const { |
269 | NodeType *child = getChild(root, elementName); | 280 | NodeType *child = getChild(root, elementName); |
270 | if (child == nullptr) { | 281 | if (child == nullptr) { |
271 | mLastError = "Could not find element with name <" + elementName + "> in element <" | 282 | *error = "Could not find element with name <" + elementName + "> in element <" + |
272 | + this->elementName() + ">"; | 283 | this->elementName() + ">"; |
273 | return false; | 284 | return false; |
274 | } | 285 | } |
275 | *s = getText(child); | 286 | *s = getText(child); |
@@ -277,14 +288,15 @@ struct XmlNodeConverter : public XmlConverter<Object> { | |||
277 | } | 288 | } |
278 | 289 | ||
279 | inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName, | 290 | inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName, |
280 | std::string&& defaultValue, std::string* s) const { | 291 | std::string&& defaultValue, std::string* s, |
292 | std::string* /* error */) const { | ||
281 | NodeType* child = getChild(root, elementName); | 293 | NodeType* child = getChild(root, elementName); |
282 | *s = child == nullptr ? std::move(defaultValue) : getText(child); | 294 | *s = child == nullptr ? std::move(defaultValue) : getText(child); |
283 | return true; | 295 | return true; |
284 | } | 296 | } |
285 | 297 | ||
286 | inline bool parseTextElements(NodeType *root, const std::string &elementName, | 298 | inline bool parseTextElements(NodeType* root, const std::string& elementName, |
287 | std::vector<std::string> *v) const { | 299 | std::vector<std::string>* v, std::string* /* error */) const { |
288 | auto nodes = getChildren(root, elementName); | 300 | auto nodes = getChildren(root, elementName); |
289 | v->resize(nodes.size()); | 301 | v->resize(nodes.size()); |
290 | for (size_t i = 0; i < nodes.size(); ++i) { | 302 | for (size_t i = 0; i < nodes.size(); ++i) { |
@@ -294,43 +306,37 @@ struct XmlNodeConverter : public XmlConverter<Object> { | |||
294 | } | 306 | } |
295 | 307 | ||
296 | template <typename T> | 308 | template <typename T> |
297 | inline bool parseChild(NodeType *root, const XmlNodeConverter<T> &conv, T *t) const { | 309 | inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t, |
310 | std::string* error) const { | ||
298 | NodeType *child = getChild(root, conv.elementName()); | 311 | NodeType *child = getChild(root, conv.elementName()); |
299 | if (child == nullptr) { | 312 | if (child == nullptr) { |
300 | mLastError = "Could not find element with name <" + conv.elementName() + "> in element <" | 313 | *error = "Could not find element with name <" + conv.elementName() + "> in element <" + |
301 | + this->elementName() + ">"; | 314 | this->elementName() + ">"; |
302 | return false; | 315 | return false; |
303 | } | 316 | } |
304 | bool success = conv.deserialize(t, child); | 317 | return conv.deserialize(t, child, error); |
305 | if (!success) { | ||
306 | mLastError = conv.lastError(); | ||
307 | } | ||
308 | return success; | ||
309 | } | 318 | } |
310 | 319 | ||
311 | template <typename T> | 320 | template <typename T> |
312 | inline bool parseOptionalChild(NodeType *root, const XmlNodeConverter<T> &conv, | 321 | inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv, |
313 | T &&defaultValue, T *t) const { | 322 | T&& defaultValue, T* t, std::string* error) const { |
314 | NodeType *child = getChild(root, conv.elementName()); | 323 | NodeType *child = getChild(root, conv.elementName()); |
315 | if (child == nullptr) { | 324 | if (child == nullptr) { |
316 | *t = std::move(defaultValue); | 325 | *t = std::move(defaultValue); |
317 | return true; | 326 | return true; |
318 | } | 327 | } |
319 | bool success = conv.deserialize(t, child); | 328 | return conv.deserialize(t, child, error); |
320 | if (!success) { | ||
321 | mLastError = conv.lastError(); | ||
322 | } | ||
323 | return success; | ||
324 | } | 329 | } |
325 | 330 | ||
326 | template <typename T> | 331 | template <typename T> |
327 | inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::vector<T> *v) const { | 332 | inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v, |
333 | std::string* error) const { | ||
328 | auto nodes = getChildren(root, conv.elementName()); | 334 | auto nodes = getChildren(root, conv.elementName()); |
329 | v->resize(nodes.size()); | 335 | v->resize(nodes.size()); |
330 | for (size_t i = 0; i < nodes.size(); ++i) { | 336 | for (size_t i = 0; i < nodes.size(); ++i) { |
331 | if (!conv.deserialize(&v->at(i), nodes[i])) { | 337 | if (!conv.deserialize(&v->at(i), nodes[i], error)) { |
332 | mLastError = "Could not parse element with name <" + conv.elementName() | 338 | *error = "Could not parse element with name <" + conv.elementName() + |
333 | + "> in element <" + this->elementName() + ">: " + conv.lastError(); | 339 | "> in element <" + this->elementName() + ">: " + *error; |
334 | return false; | 340 | return false; |
335 | } | 341 | } |
336 | } | 342 | } |
@@ -338,37 +344,39 @@ struct XmlNodeConverter : public XmlConverter<Object> { | |||
338 | } | 344 | } |
339 | 345 | ||
340 | template <typename T> | 346 | template <typename T> |
341 | inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::set<T> *s) const { | 347 | inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::set<T>* s, |
348 | std::string* error) const { | ||
342 | std::vector<T> vec; | 349 | std::vector<T> vec; |
343 | if (!parseChildren(root, conv, &vec)) { | 350 | if (!parseChildren(root, conv, &vec, error)) { |
344 | return false; | 351 | return false; |
345 | } | 352 | } |
346 | s->clear(); | 353 | s->clear(); |
347 | s->insert(vec.begin(), vec.end()); | 354 | s->insert(vec.begin(), vec.end()); |
348 | if (s->size() != vec.size()) { | 355 | if (s->size() != vec.size()) { |
349 | mLastError = "Duplicated elements <" + conv.elementName() + "> in element <" | 356 | *error = "Duplicated elements <" + conv.elementName() + "> in element <" + |
350 | + this->elementName() + ">"; | 357 | this->elementName() + ">"; |
351 | s->clear(); | 358 | s->clear(); |
352 | return false; | 359 | return false; |
353 | } | 360 | } |
354 | return true; | 361 | return true; |
355 | } | 362 | } |
356 | 363 | ||
357 | inline bool parseText(NodeType *node, std::string *s) const { | 364 | inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const { |
358 | *s = getText(node); | 365 | *s = getText(node); |
359 | return true; | 366 | return true; |
360 | } | 367 | } |
361 | 368 | ||
362 | template <typename T> | 369 | template <typename T> |
363 | inline bool parseText(NodeType *node, T *s) const { | 370 | inline bool parseText(NodeType* node, T* s, std::string* error) const { |
364 | std::string text = getText(node); | 371 | std::string text = getText(node); |
365 | bool ret = ::android::vintf::parse(text, s); | 372 | bool ret = ::android::vintf::parse(text, s); |
366 | if (!ret) { | 373 | if (!ret) { |
367 | mLastError = "Could not parse text \"" + text + "\" in element <" + elementName() + ">"; | 374 | *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">"; |
368 | } | 375 | } |
369 | return ret; | 376 | return ret; |
370 | } | 377 | } |
371 | protected: | 378 | |
379 | private: | ||
372 | mutable std::string mLastError; | 380 | mutable std::string mLastError; |
373 | }; | 381 | }; |
374 | 382 | ||
@@ -380,8 +388,8 @@ struct XmlTextConverter : public XmlNodeConverter<Object> { | |||
380 | virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override { | 388 | virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override { |
381 | appendText(root, ::android::vintf::to_string(object), d); | 389 | appendText(root, ::android::vintf::to_string(object), d); |
382 | } | 390 | } |
383 | virtual bool buildObject(Object *object, NodeType *root) const override { | 391 | virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override { |
384 | return this->parseText(root, object); | 392 | return this->parseText(root, object, error); |
385 | } | 393 | } |
386 | virtual std::string elementName() const { return mElementName; }; | 394 | virtual std::string elementName() const { return mElementName; }; |
387 | private: | 395 | private: |
@@ -390,11 +398,11 @@ private: | |||
390 | 398 | ||
391 | // ---------------------- XmlNodeConverter definitions end | 399 | // ---------------------- XmlNodeConverter definitions end |
392 | 400 | ||
393 | const XmlTextConverter<Version> versionConverter{"version"}; | 401 | XmlTextConverter<Version> versionConverter{"version"}; |
394 | 402 | ||
395 | const XmlTextConverter<VersionRange> versionRangeConverter{"version"}; | 403 | XmlTextConverter<VersionRange> versionRangeConverter{"version"}; |
396 | 404 | ||
397 | const XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"}; | 405 | XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"}; |
398 | 406 | ||
399 | struct TransportArchConverter : public XmlNodeConverter<TransportArch> { | 407 | struct TransportArchConverter : public XmlNodeConverter<TransportArch> { |
400 | std::string elementName() const override { return "transport"; } | 408 | std::string elementName() const override { return "transport"; } |
@@ -404,22 +412,22 @@ struct TransportArchConverter : public XmlNodeConverter<TransportArch> { | |||
404 | } | 412 | } |
405 | appendText(root, ::android::vintf::to_string(object.transport), d); | 413 | appendText(root, ::android::vintf::to_string(object.transport), d); |
406 | } | 414 | } |
407 | bool buildObject(TransportArch *object, NodeType *root) const override { | 415 | bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override { |
408 | if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch) || | 416 | if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) || |
409 | !parseText(root, &object->transport)) { | 417 | !parseText(root, &object->transport, error)) { |
410 | return false; | 418 | return false; |
411 | } | 419 | } |
412 | if (!object->isValid()) { | 420 | if (!object->isValid()) { |
413 | this->mLastError = "transport == " + ::android::vintf::to_string(object->transport) + | 421 | *error = "transport == " + ::android::vintf::to_string(object->transport) + |
414 | " and arch == " + ::android::vintf::to_string(object->arch) + | 422 | " and arch == " + ::android::vintf::to_string(object->arch) + |
415 | " is not a valid combination."; | 423 | " is not a valid combination."; |
416 | return false; | 424 | return false; |
417 | } | 425 | } |
418 | return true; | 426 | return true; |
419 | } | 427 | } |
420 | }; | 428 | }; |
421 | 429 | ||
422 | const TransportArchConverter transportArchConverter{}; | 430 | TransportArchConverter transportArchConverter{}; |
423 | 431 | ||
424 | struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> { | 432 | struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> { |
425 | std::string elementName() const override { return "value"; } | 433 | std::string elementName() const override { return "value"; } |
@@ -427,21 +435,22 @@ struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTyp | |||
427 | appendAttr(root, "type", object.mType); | 435 | appendAttr(root, "type", object.mType); |
428 | appendText(root, ::android::vintf::to_string(object), d); | 436 | appendText(root, ::android::vintf::to_string(object), d); |
429 | } | 437 | } |
430 | bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override { | 438 | bool buildObject(KernelConfigTypedValue* object, NodeType* root, |
439 | std::string* error) const override { | ||
431 | std::string stringValue; | 440 | std::string stringValue; |
432 | if (!parseAttr(root, "type", &object->mType) || | 441 | if (!parseAttr(root, "type", &object->mType, error) || |
433 | !parseText(root, &stringValue)) { | 442 | !parseText(root, &stringValue, error)) { |
434 | return false; | 443 | return false; |
435 | } | 444 | } |
436 | if (!::android::vintf::parseKernelConfigValue(stringValue, object)) { | 445 | if (!::android::vintf::parseKernelConfigValue(stringValue, object)) { |
437 | this->mLastError = "Could not parse kernel config value \"" + stringValue + "\""; | 446 | *error = "Could not parse kernel config value \"" + stringValue + "\""; |
438 | return false; | 447 | return false; |
439 | } | 448 | } |
440 | return true; | 449 | return true; |
441 | } | 450 | } |
442 | }; | 451 | }; |
443 | 452 | ||
444 | const KernelConfigTypedValueConverter kernelConfigTypedValueConverter{}; | 453 | KernelConfigTypedValueConverter kernelConfigTypedValueConverter{}; |
445 | 454 | ||
446 | struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> { | 455 | struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> { |
447 | std::string elementName() const override { return "config"; } | 456 | std::string elementName() const override { return "config"; } |
@@ -449,16 +458,16 @@ struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> { | |||
449 | appendChild(root, kernelConfigKeyConverter(object.first, d)); | 458 | appendChild(root, kernelConfigKeyConverter(object.first, d)); |
450 | appendChild(root, kernelConfigTypedValueConverter(object.second, d)); | 459 | appendChild(root, kernelConfigTypedValueConverter(object.second, d)); |
451 | } | 460 | } |
452 | bool buildObject(KernelConfig *object, NodeType *root) const override { | 461 | bool buildObject(KernelConfig* object, NodeType* root, std::string* error) const override { |
453 | if ( !parseChild(root, kernelConfigKeyConverter, &object->first) | 462 | if (!parseChild(root, kernelConfigKeyConverter, &object->first, error) || |
454 | || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) { | 463 | !parseChild(root, kernelConfigTypedValueConverter, &object->second, error)) { |
455 | return false; | 464 | return false; |
456 | } | 465 | } |
457 | return true; | 466 | return true; |
458 | } | 467 | } |
459 | }; | 468 | }; |
460 | 469 | ||
461 | const KernelConfigConverter kernelConfigConverter{}; | 470 | KernelConfigConverter kernelConfigConverter{}; |
462 | 471 | ||
463 | struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> { | 472 | struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> { |
464 | std::string elementName() const override { return "interface"; } | 473 | std::string elementName() const override { return "interface"; } |
@@ -466,23 +475,23 @@ struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> { | |||
466 | appendTextElement(root, "name", intf.name, d); | 475 | appendTextElement(root, "name", intf.name, d); |
467 | appendTextElements(root, "instance", intf.instances, d); | 476 | appendTextElements(root, "instance", intf.instances, d); |
468 | } | 477 | } |
469 | bool buildObject(HalInterface *intf, NodeType *root) const override { | 478 | bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override { |
470 | std::vector<std::string> instances; | 479 | std::vector<std::string> instances; |
471 | if (!parseTextElement(root, "name", &intf->name) || | 480 | if (!parseTextElement(root, "name", &intf->name, error) || |
472 | !parseTextElements(root, "instance", &instances)) { | 481 | !parseTextElements(root, "instance", &instances, error)) { |
473 | return false; | 482 | return false; |
474 | } | 483 | } |
475 | intf->instances.clear(); | 484 | intf->instances.clear(); |
476 | intf->instances.insert(instances.begin(), instances.end()); | 485 | intf->instances.insert(instances.begin(), instances.end()); |
477 | if (intf->instances.size() != instances.size()) { | 486 | if (intf->instances.size() != instances.size()) { |
478 | this->mLastError = "Duplicated instances in " + intf->name; | 487 | *error = "Duplicated instances in " + intf->name; |
479 | return false; | 488 | return false; |
480 | } | 489 | } |
481 | return true; | 490 | return true; |
482 | } | 491 | } |
483 | }; | 492 | }; |
484 | 493 | ||
485 | const HalInterfaceConverter halInterfaceConverter{}; | 494 | HalInterfaceConverter halInterfaceConverter{}; |
486 | 495 | ||
487 | struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { | 496 | struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { |
488 | std::string elementName() const override { return "hal"; } | 497 | std::string elementName() const override { return "hal"; } |
@@ -493,28 +502,29 @@ struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { | |||
493 | appendChildren(root, versionRangeConverter, hal.versionRanges, d); | 502 | appendChildren(root, versionRangeConverter, hal.versionRanges, d); |
494 | appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d); | 503 | appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d); |
495 | } | 504 | } |
496 | bool buildObject(MatrixHal *object, NodeType *root) const override { | 505 | bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override { |
497 | std::vector<HalInterface> interfaces; | 506 | std::vector<HalInterface> interfaces; |
498 | if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) || | 507 | if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) || |
499 | !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional) || | 508 | !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional, |
500 | !parseTextElement(root, "name", &object->name) || | 509 | error) || |
501 | !parseChildren(root, versionRangeConverter, &object->versionRanges) || | 510 | !parseTextElement(root, "name", &object->name, error) || |
502 | !parseChildren(root, halInterfaceConverter, &interfaces)) { | 511 | !parseChildren(root, versionRangeConverter, &object->versionRanges, error) || |
512 | !parseChildren(root, halInterfaceConverter, &interfaces, error)) { | ||
503 | return false; | 513 | return false; |
504 | } | 514 | } |
505 | for (auto&& interface : interfaces) { | 515 | for (auto&& interface : interfaces) { |
506 | std::string name{interface.name}; | 516 | std::string name{interface.name}; |
507 | auto res = object->interfaces.emplace(std::move(name), std::move(interface)); | 517 | auto res = object->interfaces.emplace(std::move(name), std::move(interface)); |
508 | if (!res.second) { | 518 | if (!res.second) { |
509 | this->mLastError = "Duplicated interface entry \"" + res.first->first + | 519 | *error = "Duplicated interface entry \"" + res.first->first + |
510 | "\"; if additional instances are needed, add them to the " | 520 | "\"; if additional instances are needed, add them to the " |
511 | "existing <interface> node."; | 521 | "existing <interface> node."; |
512 | return false; | 522 | return false; |
513 | } | 523 | } |
514 | } | 524 | } |
515 | // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally. | 525 | // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally. |
516 | #ifndef LIBVINTF_TARGET | 526 | #ifndef LIBVINTF_TARGET |
517 | if (!checkAdditionalRestrictionsOnHal(*object)) { | 527 | if (!checkAdditionalRestrictionsOnHal(*object, error)) { |
518 | return false; | 528 | return false; |
519 | } | 529 | } |
520 | #endif | 530 | #endif |
@@ -523,24 +533,24 @@ struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { | |||
523 | 533 | ||
524 | #ifndef LIBVINTF_TARGET | 534 | #ifndef LIBVINTF_TARGET |
525 | private: | 535 | private: |
526 | bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal) const { | 536 | bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const { |
527 | if (hal.getName() == "netutils-wrapper") { | 537 | if (hal.getName() == "netutils-wrapper") { |
528 | if (hal.versionRanges.size() != 1) { | 538 | if (hal.versionRanges.size() != 1) { |
529 | this->mLastError = | 539 | *error = |
530 | "netutils-wrapper HAL must specify exactly one version x.0, " | 540 | "netutils-wrapper HAL must specify exactly one version x.0, " |
531 | "but multiple <version> element is specified."; | 541 | "but multiple <version> element is specified."; |
532 | return false; | 542 | return false; |
533 | } | 543 | } |
534 | const VersionRange& v = hal.versionRanges.at(0); | 544 | const VersionRange& v = hal.versionRanges.at(0); |
535 | if (!v.isSingleVersion()) { | 545 | if (!v.isSingleVersion()) { |
536 | this->mLastError = | 546 | *error = |
537 | "netutils-wrapper HAL must specify exactly one version x.0, " | 547 | "netutils-wrapper HAL must specify exactly one version x.0, " |
538 | "but a range is provided. Perhaps you mean '" + | 548 | "but a range is provided. Perhaps you mean '" + |
539 | to_string(Version{v.majorVer, 0}) + "'?"; | 549 | to_string(Version{v.majorVer, 0}) + "'?"; |
540 | return false; | 550 | return false; |
541 | } | 551 | } |
542 | if (v.minMinor != 0) { | 552 | if (v.minMinor != 0) { |
543 | this->mLastError = | 553 | *error = |
544 | "netutils-wrapper HAL must specify exactly one version x.0, " | 554 | "netutils-wrapper HAL must specify exactly one version x.0, " |
545 | "but minor version is not 0. Perhaps you mean '" + | 555 | "but minor version is not 0. Perhaps you mean '" + |
546 | to_string(Version{v.majorVer, 0}) + "'?"; | 556 | to_string(Version{v.majorVer, 0}) + "'?"; |
@@ -552,7 +562,7 @@ struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { | |||
552 | #endif | 562 | #endif |
553 | }; | 563 | }; |
554 | 564 | ||
555 | const MatrixHalConverter matrixHalConverter{}; | 565 | MatrixHalConverter matrixHalConverter{}; |
556 | 566 | ||
557 | struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> { | 567 | struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> { |
558 | std::string elementName() const override { return "conditions"; } | 568 | std::string elementName() const override { return "conditions"; } |
@@ -560,12 +570,13 @@ struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<Ker | |||
560 | DocType* d) const override { | 570 | DocType* d) const override { |
561 | appendChildren(root, kernelConfigConverter, conds, d); | 571 | appendChildren(root, kernelConfigConverter, conds, d); |
562 | } | 572 | } |
563 | bool buildObject(std::vector<KernelConfig>* object, NodeType* root) const override { | 573 | bool buildObject(std::vector<KernelConfig>* object, NodeType* root, |
564 | return parseChildren(root, kernelConfigConverter, object); | 574 | std::string* error) const override { |
575 | return parseChildren(root, kernelConfigConverter, object, error); | ||
565 | } | 576 | } |
566 | }; | 577 | }; |
567 | 578 | ||
568 | const MatrixKernelConditionsConverter matrixKernelConditionsConverter{}; | 579 | MatrixKernelConditionsConverter matrixKernelConditionsConverter{}; |
569 | 580 | ||
570 | struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> { | 581 | struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> { |
571 | std::string elementName() const override { return "kernel"; } | 582 | std::string elementName() const override { return "kernel"; } |
@@ -576,17 +587,18 @@ struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> { | |||
576 | } | 587 | } |
577 | appendChildren(root, kernelConfigConverter, kernel.mConfigs, d); | 588 | appendChildren(root, kernelConfigConverter, kernel.mConfigs, d); |
578 | } | 589 | } |
579 | bool buildObject(MatrixKernel *object, NodeType *root) const override { | 590 | bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override { |
580 | if (!parseAttr(root, "version", &object->mMinLts) || | 591 | if (!parseAttr(root, "version", &object->mMinLts, error) || |
581 | !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions) || | 592 | !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions, |
582 | !parseChildren(root, kernelConfigConverter, &object->mConfigs)) { | 593 | error) || |
594 | !parseChildren(root, kernelConfigConverter, &object->mConfigs, error)) { | ||
583 | return false; | 595 | return false; |
584 | } | 596 | } |
585 | return true; | 597 | return true; |
586 | } | 598 | } |
587 | }; | 599 | }; |
588 | 600 | ||
589 | const MatrixKernelConverter matrixKernelConverter{}; | 601 | MatrixKernelConverter matrixKernelConverter{}; |
590 | 602 | ||
591 | struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { | 603 | struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { |
592 | std::string elementName() const override { return "hal"; } | 604 | std::string elementName() const override { return "hal"; } |
@@ -600,28 +612,27 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { | |||
600 | appendAttr(root, "override", hal.isOverride); | 612 | appendAttr(root, "override", hal.isOverride); |
601 | } | 613 | } |
602 | } | 614 | } |
603 | bool buildObject(ManifestHal *object, NodeType *root) const override { | 615 | bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override { |
604 | std::vector<HalInterface> interfaces; | 616 | std::vector<HalInterface> interfaces; |
605 | if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) || | 617 | if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) || |
606 | !parseOptionalAttr(root, "override", false, &object->isOverride) || | 618 | !parseOptionalAttr(root, "override", false, &object->isOverride, error) || |
607 | !parseTextElement(root, "name", &object->name) || | 619 | !parseTextElement(root, "name", &object->name, error) || |
608 | !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch) || | 620 | !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) || |
609 | !parseChildren(root, versionConverter, &object->versions) || | 621 | !parseChildren(root, versionConverter, &object->versions, error) || |
610 | !parseChildren(root, halInterfaceConverter, &interfaces)) { | 622 | !parseChildren(root, halInterfaceConverter, &interfaces, error)) { |
611 | return false; | 623 | return false; |
612 | } | 624 | } |
613 | 625 | ||
614 | switch (object->format) { | 626 | switch (object->format) { |
615 | case HalFormat::HIDL: { | 627 | case HalFormat::HIDL: { |
616 | if (object->transportArch.empty()) { | 628 | if (object->transportArch.empty()) { |
617 | this->mLastError = | 629 | *error = "HIDL HAL '" + object->name + "' should have <transport> defined."; |
618 | "HIDL HAL '" + object->name + "' should have <transport> defined."; | ||
619 | return false; | 630 | return false; |
620 | } | 631 | } |
621 | } break; | 632 | } break; |
622 | case HalFormat::NATIVE: { | 633 | case HalFormat::NATIVE: { |
623 | if (!object->transportArch.empty()) { | 634 | if (!object->transportArch.empty()) { |
624 | this->mLastError = | 635 | *error = |
625 | "Native HAL '" + object->name + "' should not have <transport> defined."; | 636 | "Native HAL '" + object->name + "' should not have <transport> defined."; |
626 | return false; | 637 | return false; |
627 | } | 638 | } |
@@ -639,19 +650,19 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { | |||
639 | auto res = object->interfaces.emplace(interface.name, | 650 | auto res = object->interfaces.emplace(interface.name, |
640 | std::move(interface)); | 651 | std::move(interface)); |
641 | if (!res.second) { | 652 | if (!res.second) { |
642 | this->mLastError = "Duplicated interface entry \"" + res.first->first + | 653 | *error = "Duplicated interface entry \"" + res.first->first + |
643 | "\"; if additional instances are needed, add them to the " | 654 | "\"; if additional instances are needed, add them to the " |
644 | "existing <interface> node."; | 655 | "existing <interface> node."; |
645 | return false; | 656 | return false; |
646 | } | 657 | } |
647 | } | 658 | } |
648 | if (!object->isValid()) { | 659 | if (!object->isValid()) { |
649 | this->mLastError = "'" + object->name + "' is not a valid Manifest HAL."; | 660 | *error = "'" + object->name + "' is not a valid Manifest HAL."; |
650 | return false; | 661 | return false; |
651 | } | 662 | } |
652 | // Do not check for target-side libvintf to avoid restricting upgrade accidentally. | 663 | // Do not check for target-side libvintf to avoid restricting upgrade accidentally. |
653 | #ifndef LIBVINTF_TARGET | 664 | #ifndef LIBVINTF_TARGET |
654 | if (!checkAdditionalRestrictionsOnHal(*object)) { | 665 | if (!checkAdditionalRestrictionsOnHal(*object, error)) { |
655 | return false; | 666 | return false; |
656 | } | 667 | } |
657 | #endif | 668 | #endif |
@@ -660,11 +671,11 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { | |||
660 | 671 | ||
661 | #ifndef LIBVINTF_TARGET | 672 | #ifndef LIBVINTF_TARGET |
662 | private: | 673 | private: |
663 | bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal) const { | 674 | bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const { |
664 | if (hal.getName() == "netutils-wrapper") { | 675 | if (hal.getName() == "netutils-wrapper") { |
665 | for (const Version& v : hal.versions) { | 676 | for (const Version& v : hal.versions) { |
666 | if (v.minorVer != 0) { | 677 | if (v.minorVer != 0) { |
667 | this->mLastError = | 678 | *error = |
668 | "netutils-wrapper HAL must specify exactly one version x.0, " | 679 | "netutils-wrapper HAL must specify exactly one version x.0, " |
669 | "but minor version is not 0. Perhaps you mean '" + | 680 | "but minor version is not 0. Perhaps you mean '" + |
670 | to_string(Version{v.majorVer, 0}) + "'?"; | 681 | to_string(Version{v.majorVer, 0}) + "'?"; |
@@ -679,10 +690,10 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { | |||
679 | 690 | ||
680 | // Convert ManifestHal from and to XML. Returned object is guaranteed to have | 691 | // Convert ManifestHal from and to XML. Returned object is guaranteed to have |
681 | // .isValid() == true. | 692 | // .isValid() == true. |
682 | const ManifestHalConverter manifestHalConverter{}; | 693 | ManifestHalConverter manifestHalConverter{}; |
683 | 694 | ||
684 | const XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"}; | 695 | XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"}; |
685 | const XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"}; | 696 | XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"}; |
686 | 697 | ||
687 | struct SepolicyConverter : public XmlNodeConverter<Sepolicy> { | 698 | struct SepolicyConverter : public XmlNodeConverter<Sepolicy> { |
688 | std::string elementName() const override { return "sepolicy"; } | 699 | std::string elementName() const override { return "sepolicy"; } |
@@ -690,21 +701,22 @@ struct SepolicyConverter : public XmlNodeConverter<Sepolicy> { | |||
690 | appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d)); | 701 | appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d)); |
691 | appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d); | 702 | appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d); |
692 | } | 703 | } |
693 | bool buildObject(Sepolicy *object, NodeType *root) const override { | 704 | bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override { |
694 | if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion) || | 705 | if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion, |
695 | !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges)) { | 706 | error) || |
707 | !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges, | ||
708 | error)) { | ||
696 | return false; | 709 | return false; |
697 | } | 710 | } |
698 | return true; | 711 | return true; |
699 | } | 712 | } |
700 | }; | 713 | }; |
701 | const SepolicyConverter sepolicyConverter{}; | 714 | SepolicyConverter sepolicyConverter{}; |
702 | 715 | ||
703 | [[deprecated]] | 716 | [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"}; |
704 | const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"}; | ||
705 | 717 | ||
706 | const XmlTextConverter<std::string> vndkVersionConverter{"version"}; | 718 | XmlTextConverter<std::string> vndkVersionConverter{"version"}; |
707 | const XmlTextConverter<std::string> vndkLibraryConverter{"library"}; | 719 | XmlTextConverter<std::string> vndkLibraryConverter{"library"}; |
708 | 720 | ||
709 | struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> { | 721 | struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> { |
710 | std::string elementName() const override { return "vndk"; } | 722 | std::string elementName() const override { return "vndk"; } |
@@ -712,17 +724,16 @@ struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> { | |||
712 | appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d)); | 724 | appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d)); |
713 | appendChildren(root, vndkLibraryConverter, object.mLibraries, d); | 725 | appendChildren(root, vndkLibraryConverter, object.mLibraries, d); |
714 | } | 726 | } |
715 | bool buildObject(Vndk *object, NodeType *root) const override { | 727 | bool buildObject(Vndk* object, NodeType* root, std::string* error) const override { |
716 | if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange) || | 728 | if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) || |
717 | !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) { | 729 | !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) { |
718 | return false; | 730 | return false; |
719 | } | 731 | } |
720 | return true; | 732 | return true; |
721 | } | 733 | } |
722 | }; | 734 | }; |
723 | 735 | ||
724 | [[deprecated]] | 736 | [[deprecated]] VndkConverter vndkConverter{}; |
725 | const VndkConverter vndkConverter{}; | ||
726 | 737 | ||
727 | struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> { | 738 | struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> { |
728 | std::string elementName() const override { return "vendor-ndk"; } | 739 | std::string elementName() const override { return "vendor-ndk"; } |
@@ -730,41 +741,41 @@ struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> { | |||
730 | appendChild(root, vndkVersionConverter(object.mVersion, d)); | 741 | appendChild(root, vndkVersionConverter(object.mVersion, d)); |
731 | appendChildren(root, vndkLibraryConverter, object.mLibraries, d); | 742 | appendChildren(root, vndkLibraryConverter, object.mLibraries, d); |
732 | } | 743 | } |
733 | bool buildObject(VendorNdk* object, NodeType* root) const override { | 744 | bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override { |
734 | if (!parseChild(root, vndkVersionConverter, &object->mVersion) || | 745 | if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) || |
735 | !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) { | 746 | !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) { |
736 | return false; | 747 | return false; |
737 | } | 748 | } |
738 | return true; | 749 | return true; |
739 | } | 750 | } |
740 | }; | 751 | }; |
741 | 752 | ||
742 | const VendorNdkConverter vendorNdkConverter{}; | 753 | VendorNdkConverter vendorNdkConverter{}; |
743 | 754 | ||
744 | const XmlTextConverter<std::string> systemSdkVersionConverter{"version"}; | 755 | XmlTextConverter<std::string> systemSdkVersionConverter{"version"}; |
745 | 756 | ||
746 | struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> { | 757 | struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> { |
747 | std::string elementName() const override { return "system-sdk"; } | 758 | std::string elementName() const override { return "system-sdk"; } |
748 | void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override { | 759 | void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override { |
749 | appendChildren(root, systemSdkVersionConverter, object.versions(), d); | 760 | appendChildren(root, systemSdkVersionConverter, object.versions(), d); |
750 | } | 761 | } |
751 | bool buildObject(SystemSdk* object, NodeType* root) const override { | 762 | bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override { |
752 | return parseChildren(root, systemSdkVersionConverter, &object->mVersions); | 763 | return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error); |
753 | } | 764 | } |
754 | }; | 765 | }; |
755 | 766 | ||
756 | const SystemSdkConverter systemSdkConverter{}; | 767 | SystemSdkConverter systemSdkConverter{}; |
757 | 768 | ||
758 | struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> { | 769 | struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> { |
759 | std::string elementName() const override { return "sepolicy"; } | 770 | std::string elementName() const override { return "sepolicy"; } |
760 | void mutateNode(const Version &m, NodeType *root, DocType *d) const override { | 771 | void mutateNode(const Version &m, NodeType *root, DocType *d) const override { |
761 | appendChild(root, versionConverter(m, d)); | 772 | appendChild(root, versionConverter(m, d)); |
762 | } | 773 | } |
763 | bool buildObject(Version *object, NodeType *root) const override { | 774 | bool buildObject(Version* object, NodeType* root, std::string* error) const override { |
764 | return parseChild(root, versionConverter, object); | 775 | return parseChild(root, versionConverter, object, error); |
765 | } | 776 | } |
766 | }; | 777 | }; |
767 | const HalManifestSepolicyConverter halManifestSepolicyConverter{}; | 778 | HalManifestSepolicyConverter halManifestSepolicyConverter{}; |
768 | 779 | ||
769 | struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> { | 780 | struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> { |
770 | std::string elementName() const override { return "xmlfile"; } | 781 | std::string elementName() const override { return "xmlfile"; } |
@@ -775,16 +786,16 @@ struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> { | |||
775 | appendTextElement(root, "path", f.overriddenPath(), d); | 786 | appendTextElement(root, "path", f.overriddenPath(), d); |
776 | } | 787 | } |
777 | } | 788 | } |
778 | bool buildObject(ManifestXmlFile* object, NodeType* root) const override { | 789 | bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override { |
779 | if (!parseTextElement(root, "name", &object->mName) || | 790 | if (!parseTextElement(root, "name", &object->mName, error) || |
780 | !parseChild(root, versionConverter, &object->mVersion) || | 791 | !parseChild(root, versionConverter, &object->mVersion, error) || |
781 | !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) { | 792 | !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) { |
782 | return false; | 793 | return false; |
783 | } | 794 | } |
784 | return true; | 795 | return true; |
785 | } | 796 | } |
786 | }; | 797 | }; |
787 | const ManifestXmlFileConverter manifestXmlFileConverter{}; | 798 | ManifestXmlFileConverter manifestXmlFileConverter{}; |
788 | 799 | ||
789 | struct HalManifestConverter : public XmlNodeConverter<HalManifest> { | 800 | struct HalManifestConverter : public XmlNodeConverter<HalManifest> { |
790 | std::string elementName() const override { return "manifest"; } | 801 | std::string elementName() const override { return "manifest"; } |
@@ -826,17 +837,17 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> { | |||
826 | appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d); | 837 | appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d); |
827 | } | 838 | } |
828 | } | 839 | } |
829 | bool buildObject(HalManifest *object, NodeType *root) const override { | 840 | bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override { |
830 | std::vector<ManifestHal> hals; | 841 | std::vector<ManifestHal> hals; |
831 | if (!parseAttr(root, "version", &object->mMetaVersion) || | 842 | if (!parseAttr(root, "version", &object->mMetaVersion, error) || |
832 | !parseAttr(root, "type", &object->mType) || | 843 | !parseAttr(root, "type", &object->mType, error) || |
833 | !parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel) || | 844 | !parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel, error) || |
834 | !parseChildren(root, manifestHalConverter, &hals)) { | 845 | !parseChildren(root, manifestHalConverter, &hals, error)) { |
835 | return false; | 846 | return false; |
836 | } | 847 | } |
837 | if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) { | 848 | if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) { |
838 | this->mLastError = "Unrecognized manifest.version " + to_string(object->mMetaVersion) + | 849 | *error = "Unrecognized manifest.version " + to_string(object->mMetaVersion) + |
839 | " (libvintf@" + to_string(kMetaVersion) + ")"; | 850 | " (libvintf@" + to_string(kMetaVersion) + ")"; |
840 | return false; | 851 | return false; |
841 | } | 852 | } |
842 | if (object->mType == SchemaType::DEVICE) { | 853 | if (object->mType == SchemaType::DEVICE) { |
@@ -844,59 +855,59 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> { | |||
844 | // <sepolicy> can be missing because it can be determined at build time, not hard-coded | 855 | // <sepolicy> can be missing because it can be determined at build time, not hard-coded |
845 | // in the XML file. | 856 | // in the XML file. |
846 | if (!parseOptionalChild(root, halManifestSepolicyConverter, {}, | 857 | if (!parseOptionalChild(root, halManifestSepolicyConverter, {}, |
847 | &object->device.mSepolicyVersion)) { | 858 | &object->device.mSepolicyVersion, error)) { |
848 | return false; | 859 | return false; |
849 | } | 860 | } |
850 | } else if (object->mType == SchemaType::FRAMEWORK) { | 861 | } else if (object->mType == SchemaType::FRAMEWORK) { |
851 | #pragma clang diagnostic push | 862 | #pragma clang diagnostic push |
852 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 863 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
853 | if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) { | 864 | if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) { |
854 | return false; | 865 | return false; |
855 | } | 866 | } |
856 | for (const auto &vndk : object->framework.mVndks) { | 867 | for (const auto &vndk : object->framework.mVndks) { |
857 | if (!vndk.mVersionRange.isSingleVersion()) { | 868 | if (!vndk.mVersionRange.isSingleVersion()) { |
858 | this->mLastError = "vndk.version " + to_string(vndk.mVersionRange) | 869 | *error = "vndk.version " + to_string(vndk.mVersionRange) + |
859 | + " cannot be a range for manifests"; | 870 | " cannot be a range for manifests"; |
860 | return false; | 871 | return false; |
861 | } | 872 | } |
862 | } | 873 | } |
863 | #pragma clang diagnostic pop | 874 | #pragma clang diagnostic pop |
864 | 875 | ||
865 | if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks)) { | 876 | if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) { |
866 | return false; | 877 | return false; |
867 | } | 878 | } |
868 | 879 | ||
869 | std::set<std::string> vendorNdkVersions; | 880 | std::set<std::string> vendorNdkVersions; |
870 | for (const auto& vendorNdk : object->framework.mVendorNdks) { | 881 | for (const auto& vendorNdk : object->framework.mVendorNdks) { |
871 | if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) { | 882 | if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) { |
872 | this->mLastError = | 883 | *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version(); |
873 | "Duplicated manifest.vendor-ndk.version " + vendorNdk.version(); | ||
874 | return false; | 884 | return false; |
875 | } | 885 | } |
876 | vendorNdkVersions.insert(vendorNdk.version()); | 886 | vendorNdkVersions.insert(vendorNdk.version()); |
877 | } | 887 | } |
878 | 888 | ||
879 | if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk)) { | 889 | if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk, |
890 | error)) { | ||
880 | return false; | 891 | return false; |
881 | } | 892 | } |
882 | } | 893 | } |
883 | for (auto &&hal : hals) { | 894 | for (auto &&hal : hals) { |
884 | std::string description{hal.name}; | 895 | std::string description{hal.name}; |
885 | if (!object->add(std::move(hal))) { | 896 | if (!object->add(std::move(hal))) { |
886 | this->mLastError = "Duplicated manifest.hal entry " + description; | 897 | *error = "Duplicated manifest.hal entry " + description; |
887 | return false; | 898 | return false; |
888 | } | 899 | } |
889 | } | 900 | } |
890 | 901 | ||
891 | std::vector<ManifestXmlFile> xmlFiles; | 902 | std::vector<ManifestXmlFile> xmlFiles; |
892 | if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles)) { | 903 | if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) { |
893 | return false; | 904 | return false; |
894 | } | 905 | } |
895 | for (auto&& xmlFile : xmlFiles) { | 906 | for (auto&& xmlFile : xmlFiles) { |
896 | std::string description{xmlFile.name()}; | 907 | std::string description{xmlFile.name()}; |
897 | if (!object->addXmlFile(std::move(xmlFile))) { | 908 | if (!object->addXmlFile(std::move(xmlFile))) { |
898 | this->mLastError = "Duplicated manifest.xmlfile entry " + description + | 909 | *error = "Duplicated manifest.xmlfile entry " + description + |
899 | "; entries cannot have duplicated name and version"; | 910 | "; entries cannot have duplicated name and version"; |
900 | return false; | 911 | return false; |
901 | } | 912 | } |
902 | } | 913 | } |
@@ -905,19 +916,19 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> { | |||
905 | } | 916 | } |
906 | }; | 917 | }; |
907 | 918 | ||
908 | const HalManifestConverter halManifestConverter{}; | 919 | HalManifestConverter halManifestConverter{}; |
909 | 920 | ||
910 | const XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"}; | 921 | XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"}; |
911 | struct AvbConverter : public XmlNodeConverter<Version> { | 922 | struct AvbConverter : public XmlNodeConverter<Version> { |
912 | std::string elementName() const override { return "avb"; } | 923 | std::string elementName() const override { return "avb"; } |
913 | void mutateNode(const Version &m, NodeType *root, DocType *d) const override { | 924 | void mutateNode(const Version &m, NodeType *root, DocType *d) const override { |
914 | appendChild(root, avbVersionConverter(m, d)); | 925 | appendChild(root, avbVersionConverter(m, d)); |
915 | } | 926 | } |
916 | bool buildObject(Version *object, NodeType *root) const override { | 927 | bool buildObject(Version* object, NodeType* root, std::string* error) const override { |
917 | return parseChild(root, avbVersionConverter, object); | 928 | return parseChild(root, avbVersionConverter, object, error); |
918 | } | 929 | } |
919 | }; | 930 | }; |
920 | const AvbConverter avbConverter{}; | 931 | AvbConverter avbConverter{}; |
921 | 932 | ||
922 | struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> { | 933 | struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> { |
923 | std::string elementName() const override { return "xmlfile"; } | 934 | std::string elementName() const override { return "xmlfile"; } |
@@ -930,18 +941,18 @@ struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> { | |||
930 | appendTextElement(root, "path", f.overriddenPath(), d); | 941 | appendTextElement(root, "path", f.overriddenPath(), d); |
931 | } | 942 | } |
932 | } | 943 | } |
933 | bool buildObject(MatrixXmlFile* object, NodeType* root) const override { | 944 | bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override { |
934 | if (!parseTextElement(root, "name", &object->mName) || | 945 | if (!parseTextElement(root, "name", &object->mName, error) || |
935 | !parseAttr(root, "format", &object->mFormat) || | 946 | !parseAttr(root, "format", &object->mFormat, error) || |
936 | !parseOptionalAttr(root, "optional", false, &object->mOptional) || | 947 | !parseOptionalAttr(root, "optional", false, &object->mOptional, error) || |
937 | !parseChild(root, versionRangeConverter, &object->mVersionRange) || | 948 | !parseChild(root, versionRangeConverter, &object->mVersionRange, error) || |
938 | !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) { | 949 | !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) { |
939 | return false; | 950 | return false; |
940 | } | 951 | } |
941 | return true; | 952 | return true; |
942 | } | 953 | } |
943 | }; | 954 | }; |
944 | const MatrixXmlFileConverter matrixXmlFileConverter{}; | 955 | MatrixXmlFileConverter matrixXmlFileConverter{}; |
945 | 956 | ||
946 | struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> { | 957 | struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> { |
947 | std::string elementName() const override { return "compatibility-matrix"; } | 958 | std::string elementName() const override { return "compatibility-matrix"; } |
@@ -998,21 +1009,25 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri | |||
998 | appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d); | 1009 | appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d); |
999 | } | 1010 | } |
1000 | } | 1011 | } |
1001 | bool buildObject(CompatibilityMatrix *object, NodeType *root) const override { | 1012 | bool buildObject(CompatibilityMatrix* object, NodeType* root, |
1013 | std::string* error) const override { | ||
1002 | Version version; | 1014 | Version version; |
1003 | std::vector<MatrixHal> hals; | 1015 | std::vector<MatrixHal> hals; |
1004 | if (!parseAttr(root, "version", &version) || !parseAttr(root, "type", &object->mType) || | 1016 | if (!parseAttr(root, "version", &version, error) || |
1005 | !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel) || | 1017 | !parseAttr(root, "type", &object->mType, error) || |
1006 | !parseChildren(root, matrixHalConverter, &hals)) { | 1018 | !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error) || |
1019 | !parseChildren(root, matrixHalConverter, &hals, error)) { | ||
1007 | return false; | 1020 | return false; |
1008 | } | 1021 | } |
1009 | 1022 | ||
1010 | if (object->mType == SchemaType::FRAMEWORK) { | 1023 | if (object->mType == SchemaType::FRAMEWORK) { |
1011 | // <avb> and <sepolicy> can be missing because it can be determined at build time, not | 1024 | // <avb> and <sepolicy> can be missing because it can be determined at build time, not |
1012 | // hard-coded in the XML file. | 1025 | // hard-coded in the XML file. |
1013 | if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels) || | 1026 | if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) || |
1014 | !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy) || | 1027 | !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy, |
1015 | !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion)) { | 1028 | error) || |
1029 | !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion, | ||
1030 | error)) { | ||
1016 | return false; | 1031 | return false; |
1017 | } | 1032 | } |
1018 | 1033 | ||
@@ -1023,8 +1038,8 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri | |||
1023 | continue; | 1038 | continue; |
1024 | } | 1039 | } |
1025 | if (!kernel.conditions().empty()) { | 1040 | if (!kernel.conditions().empty()) { |
1026 | this->mLastError = "First <kernel> for version " + to_string(minLts) + | 1041 | *error = "First <kernel> for version " + to_string(minLts) + |
1027 | " must have empty <conditions> for backwards compatibility."; | 1042 | " must have empty <conditions> for backwards compatibility."; |
1028 | return false; | 1043 | return false; |
1029 | } | 1044 | } |
1030 | seenKernelVersions.insert(minLts); | 1045 | seenKernelVersions.insert(minLts); |
@@ -1035,45 +1050,47 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri | |||
1035 | // in the XML file. | 1050 | // in the XML file. |
1036 | #pragma clang diagnostic push | 1051 | #pragma clang diagnostic push |
1037 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 1052 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
1038 | if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) { | 1053 | if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) { |
1039 | return false; | 1054 | return false; |
1040 | } | 1055 | } |
1041 | #pragma clang diagnostic pop | 1056 | #pragma clang diagnostic pop |
1042 | 1057 | ||
1043 | if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk)) { | 1058 | if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk, |
1059 | error)) { | ||
1044 | return false; | 1060 | return false; |
1045 | } | 1061 | } |
1046 | 1062 | ||
1047 | if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk)) { | 1063 | if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk, |
1064 | error)) { | ||
1048 | return false; | 1065 | return false; |
1049 | } | 1066 | } |
1050 | } | 1067 | } |
1051 | 1068 | ||
1052 | if (!kMetaVersion.minorAtLeast(version)) { | 1069 | if (!kMetaVersion.minorAtLeast(version)) { |
1053 | this->mLastError = "Unrecognized compatibility-matrix.version " + to_string(version) + | 1070 | *error = "Unrecognized compatibility-matrix.version " + to_string(version) + |
1054 | " (libvintf@" + to_string(kMetaVersion) + ")"; | 1071 | " (libvintf@" + to_string(kMetaVersion) + ")"; |
1055 | return false; | 1072 | return false; |
1056 | } | 1073 | } |
1057 | for (auto &&hal : hals) { | 1074 | for (auto &&hal : hals) { |
1058 | if (!object->add(std::move(hal))) { | 1075 | if (!object->add(std::move(hal))) { |
1059 | this->mLastError = "Duplicated compatibility-matrix.hal entry"; | 1076 | *error = "Duplicated compatibility-matrix.hal entry"; |
1060 | return false; | 1077 | return false; |
1061 | } | 1078 | } |
1062 | } | 1079 | } |
1063 | 1080 | ||
1064 | std::vector<MatrixXmlFile> xmlFiles; | 1081 | std::vector<MatrixXmlFile> xmlFiles; |
1065 | if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles)) { | 1082 | if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) { |
1066 | return false; | 1083 | return false; |
1067 | } | 1084 | } |
1068 | for (auto&& xmlFile : xmlFiles) { | 1085 | for (auto&& xmlFile : xmlFiles) { |
1069 | if (!xmlFile.optional()) { | 1086 | if (!xmlFile.optional()) { |
1070 | this->mLastError = "compatibility-matrix.xmlfile entry " + xmlFile.name() + | 1087 | *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() + |
1071 | " has to be optional for compatibility matrix version 1.0"; | 1088 | " has to be optional for compatibility matrix version 1.0"; |
1072 | return false; | 1089 | return false; |
1073 | } | 1090 | } |
1074 | std::string description{xmlFile.name()}; | 1091 | std::string description{xmlFile.name()}; |
1075 | if (!object->addXmlFile(std::move(xmlFile))) { | 1092 | if (!object->addXmlFile(std::move(xmlFile))) { |
1076 | this->mLastError = "Duplicated compatibility-matrix.xmlfile entry " + description; | 1093 | *error = "Duplicated compatibility-matrix.xmlfile entry " + description; |
1077 | return false; | 1094 | return false; |
1078 | } | 1095 | } |
1079 | } | 1096 | } |
@@ -1082,19 +1099,18 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri | |||
1082 | } | 1099 | } |
1083 | }; | 1100 | }; |
1084 | 1101 | ||
1085 | const CompatibilityMatrixConverter compatibilityMatrixConverter{}; | 1102 | CompatibilityMatrixConverter compatibilityMatrixConverter{}; |
1086 | 1103 | ||
1087 | // Publicly available as in parse_xml.h | 1104 | // Publicly available as in parse_xml.h |
1088 | const XmlConverter<HalManifest> &gHalManifestConverter = halManifestConverter; | 1105 | XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter; |
1089 | const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter | 1106 | XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter; |
1090 | = compatibilityMatrixConverter; | ||
1091 | 1107 | ||
1092 | // For testing in LibVintfTest | 1108 | // For testing in LibVintfTest |
1093 | const XmlConverter<Version> &gVersionConverter = versionConverter; | 1109 | XmlConverter<Version>& gVersionConverter = versionConverter; |
1094 | const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter | 1110 | XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter = |
1095 | = kernelConfigTypedValueConverter; | 1111 | kernelConfigTypedValueConverter; |
1096 | const XmlConverter<MatrixHal> &gMatrixHalConverter = matrixHalConverter; | 1112 | XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter; |
1097 | const XmlConverter<ManifestHal> &gManifestHalConverter = manifestHalConverter; | 1113 | XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter; |
1098 | 1114 | ||
1099 | } // namespace vintf | 1115 | } // namespace vintf |
1100 | } // namespace android | 1116 | } // namespace android |