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