Home | History | Annotate | Download | only in view_compiler
      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:
     33   explicit LayoutCompilerVisitor(Builder* builder) : builder_{builder} {}
     34 
     35   void VisitStartDocument() { builder_->Start(); }
     36   void VisitEndDocument() { builder_->Finish(); }
     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   }
     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 
     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