• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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