1 /* 2 * Copyright (C) 2018 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 DEX_LAYOUT_COMPILER_H_ 18 #define DEX_LAYOUT_COMPILER_H_ 19 20 #include "dex_builder.h" 21 22 #include <codecvt> 23 #include <locale> 24 #include <string> 25 #include <vector> 26 27 namespace startop { 28 29 // This visitor does the actual view compilation, using a supplied builder. 30 template <typename Builder> 31 class LayoutCompilerVisitor { 32 public: LayoutCompilerVisitor(Builder * builder)33 explicit LayoutCompilerVisitor(Builder* builder) : builder_{builder} {} 34 VisitStartDocument()35 void VisitStartDocument() { builder_->Start(); } VisitEndDocument()36 void VisitEndDocument() { builder_->Finish(); } VisitStartTag(const std::u16string & name)37 void VisitStartTag(const std::u16string& name) { 38 parent_stack_.push_back(ViewEntry{ 39 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(name), {}}); 40 } VisitEndTag()41 void VisitEndTag() { 42 auto entry = parent_stack_.back(); 43 parent_stack_.pop_back(); 44 45 if (parent_stack_.empty()) { 46 GenerateCode(entry); 47 } else { 48 parent_stack_.back().children.push_back(entry); 49 } 50 } 51 52 private: 53 struct ViewEntry { 54 std::string name; 55 std::vector<ViewEntry> children; 56 }; 57 GenerateCode(const ViewEntry & view)58 void GenerateCode(const ViewEntry& view) { 59 builder_->StartView(view.name, !view.children.empty()); 60 for (const auto& child : view.children) { 61 GenerateCode(child); 62 } 63 builder_->FinishView(); 64 } 65 66 Builder* builder_; 67 68 std::vector<ViewEntry> parent_stack_; 69 }; 70 71 class DexViewBuilder { 72 public: 73 DexViewBuilder(dex::MethodBuilder* method); 74 75 void Start(); 76 void Finish(); 77 void StartView(const std::string& name, bool is_viewgroup); 78 void FinishView(); 79 80 private: 81 // Accessors for the stack of views that are under construction. 82 dex::Value AcquireRegister(); 83 void ReleaseRegister(); 84 dex::Value GetCurrentView() const; 85 dex::Value GetCurrentLayoutParams() const; 86 dex::Value GetParentView() const; 87 void PopViewStack(); 88 89 dex::MethodBuilder* method_; 90 91 // Registers used for code generation 92 dex::Value const context_; 93 dex::Value const resid_; 94 const dex::Value inflater_; 95 const dex::Value xml_; 96 const dex::Value attrs_; 97 const dex::Value classname_tmp_; 98 99 const dex::MethodDeclData xml_next_; 100 const dex::MethodDeclData try_create_view_; 101 const dex::MethodDeclData generate_layout_params_; 102 const dex::MethodDeclData add_view_; 103 104 // used for keeping track of which registers are in use 105 size_t top_register_{0}; 106 std::vector<dex::Value> register_stack_; 107 108 // Keep track of the views currently in progress. 109 struct ViewEntry { 110 dex::Value view; 111 std::optional<dex::Value> layout_params; 112 }; 113 std::vector<ViewEntry> view_stack_; 114 }; 115 116 } // namespace startop 117 118 #endif // DEX_LAYOUT_COMPILER_H_ 119