• 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::LiveRegister AcquireRegister();
83   dex::Value GetCurrentView() const;
84   dex::Value GetCurrentLayoutParams() const;
85   dex::Value GetParentView() const;
86   void PopViewStack();
87 
88   // Methods to simplify building different code fragments.
89   void BuildGetLayoutInflater(dex::Value dest);
90   void BuildGetResources(dex::Value dest);
91   void BuildGetLayoutResource(dex::Value dest, dex::Value resources, dex::Value resid);
92   void BuildLayoutResourceToAttributeSet(dex::Value dest, dex::Value layout_resource);
93   void BuildXmlNext();
94   void BuildTryCreateView(dex::Value dest, dex::Value parent, dex::Value classname);
95 
96   dex::MethodBuilder* method_;
97 
98   // Parameters to the generated method
99   dex::Value const context_;
100   dex::Value const resid_;
101 
102   // Registers used for code generation
103   const dex::LiveRegister inflater_;
104   const dex::LiveRegister xml_;
105   const dex::LiveRegister attrs_;
106   const dex::LiveRegister classname_tmp_;
107 
108   const dex::MethodDeclData xml_next_;
109   const dex::MethodDeclData try_create_view_;
110   const dex::MethodDeclData generate_layout_params_;
111   const dex::MethodDeclData add_view_;
112 
113   // Keep track of the views currently in progress.
114   struct ViewEntry {
115     dex::LiveRegister view;
116     std::optional<dex::LiveRegister> layout_params;
117   };
118   std::vector<ViewEntry> view_stack_;
119 };
120 
121 }  // namespace startop
122 
123 #endif  // DEX_LAYOUT_COMPILER_H_
124