| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_ |
| #define IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_ |
| |
| #include <iostream> |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include "ResourceUtils.h" |
| #include "Result.h" |
| #include "android-base/macros.h" |
| #include "androidfw/ResourceTypes.h" |
| #include "utils/String16.h" |
| |
| namespace android::idmap2 { |
| |
| struct XmlParser { |
| using Event = ResXMLParser::event_code_t; |
| class iterator; |
| |
| class Node { |
| public: |
| Event event() const; |
| std::string name() const; |
| |
| Result<Res_value> GetAttributeValue(const std::string& name) const; |
| Result<Res_value> GetAttributeValue(ResourceId attr, const std::string& label) const; |
| |
| Result<std::string> GetAttributeStringValue(const std::string& name) const; |
| Result<std::string> GetAttributeStringValue(ResourceId attr, const std::string& label) const; |
| |
| bool operator==(const Node& rhs) const; |
| bool operator!=(const Node& rhs) const; |
| |
| private: |
| explicit Node(const ResXMLTree& tree); |
| Node(const ResXMLTree& tree, const ResXMLParser::ResXMLPosition& pos); |
| |
| // Retrieves/Sets the position of the position of the xml parser in the xml tree. |
| ResXMLParser::ResXMLPosition get_position() const; |
| void set_position(const ResXMLParser::ResXMLPosition& pos); |
| |
| // If `inner_child` is true, seek advances the parser to the first inner child of the current |
| // node. Otherwise, seek advances the parser to the following node. Returns false if there is |
| // no node to seek to. |
| bool Seek(bool inner_child); |
| |
| ResXMLParser parser_; |
| friend iterator; |
| }; |
| |
| class iterator { |
| public: |
| iterator(const iterator& other) : iterator(other.tree_, other.iter_) { |
| } |
| |
| inline iterator& operator=(const iterator& rhs) { |
| iter_.set_position(rhs.iter_.get_position()); |
| return *this; |
| } |
| |
| inline bool operator==(const iterator& rhs) const { |
| return iter_ == rhs.iter_; |
| } |
| |
| inline bool operator!=(const iterator& rhs) const { |
| return !(*this == rhs); |
| } |
| |
| inline iterator operator++() { |
| // Seek to the following xml node. |
| iter_.Seek(false /* inner_child */); |
| return *this; |
| } |
| |
| iterator begin() const { |
| iterator child_it(*this); |
| // Seek to the first inner child of the current node. |
| child_it.iter_.Seek(true /* inner_child */); |
| return child_it; |
| } |
| |
| iterator end() const { |
| iterator child_it = begin(); |
| while (child_it.iter_.Seek(false /* inner_child */)) { |
| // Continue iterating until the end tag is found. |
| } |
| |
| return child_it; |
| } |
| |
| inline const Node operator*() { |
| return Node(tree_, iter_.get_position()); |
| } |
| |
| inline const Node* operator->() { |
| return &iter_; |
| } |
| |
| private: |
| explicit iterator(const ResXMLTree& tree) : tree_(tree), iter_(Node(tree)) { |
| } |
| iterator(const ResXMLTree& tree, const Node& node) |
| : tree_(tree), iter_(Node(tree, node.get_position())) { |
| } |
| |
| const ResXMLTree& tree_; |
| Node iter_; |
| friend XmlParser; |
| }; |
| |
| // Creates a new xml parser beginning at the first tag. |
| static Result<XmlParser> Create(const void* data, size_t size, bool copy_data = false); |
| |
| inline iterator tree_iterator() const { |
| return iterator(*tree_); |
| } |
| |
| inline const ResStringPool& get_strings() const { |
| return tree_->getStrings(); |
| } |
| |
| private: |
| explicit XmlParser(std::unique_ptr<ResXMLTree> tree); |
| mutable std::unique_ptr<ResXMLTree> tree_; |
| }; |
| |
| } // namespace android::idmap2 |
| |
| #endif // IDMAP2_INCLUDE_IDMAP2_XMLPARSER_H_ |