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 "Result.h" 26 #include "android-base/macros.h" 27 #include "androidfw/ResourceTypes.h" 28 #include "utils/String16.h" 29 30 namespace android::idmap2 { 31 32 class XmlParser { 33 public: 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<std::string> GetAttributeStringValue(const std::string& name) const; 43 Result<Res_value> GetAttributeValue(const std::string& name) const; 44 45 bool operator==(const Node& rhs) const; 46 bool operator!=(const Node& rhs) const; 47 48 private: 49 explicit Node(const ResXMLTree& tree); 50 Node(const ResXMLTree& tree, const ResXMLParser::ResXMLPosition& pos); 51 52 // Retrieves/Sets the position of the position of the xml parser in the xml tree. 53 ResXMLParser::ResXMLPosition get_position() const; 54 void set_position(const ResXMLParser::ResXMLPosition& pos); 55 56 // If `inner_child` is true, seek advances the parser to the first inner child of the current 57 // node. Otherwise, seek advances the parser to the following node. Returns false if there is 58 // no node to seek to. 59 bool Seek(bool inner_child); 60 61 ResXMLParser parser_; 62 friend iterator; 63 }; 64 65 class iterator { 66 public: iterator(const iterator & other)67 iterator(const iterator& other) : iterator(other.tree_, other.iter_) { 68 } 69 70 inline iterator& operator=(const iterator& rhs) { 71 iter_.set_position(rhs.iter_.get_position()); 72 return *this; 73 } 74 75 inline bool operator==(const iterator& rhs) const { 76 return iter_ == rhs.iter_; 77 } 78 79 inline bool operator!=(const iterator& rhs) const { 80 return !(*this == rhs); 81 } 82 83 inline iterator operator++() { 84 // Seek to the following xml node. 85 iter_.Seek(false /* inner_child */); 86 return *this; 87 } 88 begin()89 iterator begin() const { 90 iterator child_it(*this); 91 // Seek to the first inner child of the current node. 92 child_it.iter_.Seek(true /* inner_child */); 93 return child_it; 94 } 95 end()96 iterator end() const { 97 iterator child_it = begin(); 98 while (child_it.iter_.Seek(false /* inner_child */)) { 99 // Continue iterating until the end tag is found. 100 } 101 102 return child_it; 103 } 104 105 inline const Node operator*() { 106 return Node(tree_, iter_.get_position()); 107 } 108 109 inline const Node* operator->() { 110 return &iter_; 111 } 112 113 private: iterator(const ResXMLTree & tree)114 explicit iterator(const ResXMLTree& tree) : tree_(tree), iter_(Node(tree)) { 115 } iterator(const ResXMLTree & tree,const Node & node)116 iterator(const ResXMLTree& tree, const Node& node) 117 : tree_(tree), iter_(Node(tree, node.get_position())) { 118 } 119 120 const ResXMLTree& tree_; 121 Node iter_; 122 friend XmlParser; 123 }; 124 125 // Creates a new xml parser beginning at the first tag. 126 static Result<std::unique_ptr<const XmlParser>> Create(const void* data, size_t size, 127 bool copy_data = false); 128 ~XmlParser(); 129 tree_iterator()130 inline iterator tree_iterator() const { 131 return iterator(tree_); 132 } 133 get_strings()134 inline const ResStringPool& get_strings() const { 135 return tree_.getStrings(); 136 } 137 138 private: 139 XmlParser() = default; 140 mutable ResXMLTree tree_; 141 142 DISALLOW_COPY_AND_ASSIGN(XmlParser); 143 }; 144 145 } // namespace android::idmap2 146 147 #endif // IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_ 148