1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_ 18 #define IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_ 19 20 #include <iostream> 21 #include <map> 22 #include <memory> 23 #include <string> 24 25 #include "ResourceUtils.h" 26 #include "Result.h" 27 #include "android-base/macros.h" 28 #include "androidfw/ResourceTypes.h" 29 #include "utils/String16.h" 30 31 namespace android::idmap2 { 32 33 struct XmlParser { 34 using Event = ResXMLParser::event_code_t; 35 class iterator; 36 37 class Node { 38 public: 39 Event event() const; 40 std::string name() const; 41 42 Result<Res_value> GetAttributeValue(const std::string& name) const; 43 Result<Res_value> GetAttributeValue(ResourceId attr, const std::string& label) const; 44 45 Result<std::string> GetAttributeStringValue(const std::string& name) const; 46 Result<std::string> GetAttributeStringValue(ResourceId attr, const std::string& label) const; 47 48 bool operator==(const Node& rhs) const; 49 bool operator!=(const Node& rhs) const; 50 51 private: 52 explicit Node(const ResXMLTree& tree); 53 Node(const ResXMLTree& tree, const ResXMLParser::ResXMLPosition& pos); 54 55 // Retrieves/Sets the position of the position of the xml parser in the xml tree. 56 ResXMLParser::ResXMLPosition get_position() const; 57 void set_position(const ResXMLParser::ResXMLPosition& pos); 58 59 // If `inner_child` is true, seek advances the parser to the first inner child of the current 60 // node. Otherwise, seek advances the parser to the following node. Returns false if there is 61 // no node to seek to. 62 bool Seek(bool inner_child); 63 64 ResXMLParser parser_; 65 friend iterator; 66 }; 67 68 class iterator { 69 public: iteratorXmlParser70 iterator(const iterator& other) : iterator(other.tree_, other.iter_) { 71 } 72 73 inline iterator& operator=(const iterator& rhs) { 74 iter_.set_position(rhs.iter_.get_position()); 75 return *this; 76 } 77 78 inline bool operator==(const iterator& rhs) const { 79 return iter_ == rhs.iter_; 80 } 81 82 inline bool operator!=(const iterator& rhs) const { 83 return !(*this == rhs); 84 } 85 86 inline iterator operator++() { 87 // Seek to the following xml node. 88 iter_.Seek(false /* inner_child */); 89 return *this; 90 } 91 beginXmlParser92 iterator begin() const { 93 iterator child_it(*this); 94 // Seek to the first inner child of the current node. 95 child_it.iter_.Seek(true /* inner_child */); 96 return child_it; 97 } 98 endXmlParser99 iterator end() const { 100 iterator child_it = begin(); 101 while (child_it.iter_.Seek(false /* inner_child */)) { 102 // Continue iterating until the end tag is found. 103 } 104 105 return child_it; 106 } 107 108 inline const Node operator*() { 109 return Node(tree_, iter_.get_position()); 110 } 111 112 inline const Node* operator->() { 113 return &iter_; 114 } 115 116 private: iteratorXmlParser117 explicit iterator(const ResXMLTree& tree) : tree_(tree), iter_(Node(tree)) { 118 } iteratorXmlParser119 iterator(const ResXMLTree& tree, const Node& node) 120 : tree_(tree), iter_(Node(tree, node.get_position())) { 121 } 122 123 const ResXMLTree& tree_; 124 Node iter_; 125 friend XmlParser; 126 }; 127 128 // Creates a new xml parser beginning at the first tag. 129 static Result<XmlParser> Create(const void* data, size_t size, bool copy_data = false); 130 tree_iteratorXmlParser131 inline iterator tree_iterator() const { 132 return iterator(*tree_); 133 } 134 get_stringsXmlParser135 inline const ResStringPool& get_strings() const { 136 return tree_->getStrings(); 137 } 138 139 private: 140 explicit XmlParser(std::unique_ptr<ResXMLTree> tree); 141 mutable std::unique_ptr<ResXMLTree> tree_; 142 }; 143 144 } // namespace android::idmap2 145 146 #endif // IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_ 147