Home | History | Annotate | Download | only in aapt2
      1 /*
      2  * Copyright (C) 2015 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 AAPT_NAME_MANGLER_H
     18 #define AAPT_NAME_MANGLER_H
     19 
     20 #include <set>
     21 #include <string>
     22 
     23 #include "Resource.h"
     24 #include "util/Maybe.h"
     25 
     26 namespace aapt {
     27 
     28 struct NameManglerPolicy {
     29   /**
     30    * Represents the package we are trying to build. References pointing
     31    * to this package are not mangled, and mangled references inherit this
     32    * package name.
     33    */
     34   std::string target_package_name;
     35 
     36   /**
     37    * We must know which references to mangle, and which to keep (android vs.
     38    * com.android.support).
     39    */
     40   std::set<std::string> packages_to_mangle;
     41 };
     42 
     43 class NameMangler {
     44  public:
     45   explicit NameMangler(NameManglerPolicy policy) : policy_(policy) {}
     46 
     47   Maybe<ResourceName> MangleName(const ResourceName& name) {
     48     if (policy_.target_package_name == name.package ||
     49         policy_.packages_to_mangle.count(name.package) == 0) {
     50       return {};
     51     }
     52 
     53     std::string mangled_entry_name = MangleEntry(name.package, name.entry);
     54     return ResourceName(policy_.target_package_name, name.type,
     55                         mangled_entry_name);
     56   }
     57 
     58   bool ShouldMangle(const std::string& package) const {
     59     if (package.empty() || policy_.target_package_name == package) {
     60       return false;
     61     }
     62     return policy_.packages_to_mangle.count(package) != 0;
     63   }
     64 
     65   const std::string& GetTargetPackageName() const { return policy_.target_package_name; }
     66 
     67   /**
     68    * Returns a mangled name that is a combination of `name` and `package`.
     69    * The mangled name should contain symbols that are illegal to define in XML,
     70    * so that there will never be name mangling collisions.
     71    */
     72   static std::string MangleEntry(const std::string& package, const std::string& name) {
     73     return package + "$" + name;
     74   }
     75 
     76   /**
     77    * Unmangles the name in `outName`, storing the correct name back in `outName`
     78    * and the package in `outPackage`. Returns true if the name was unmangled or
     79    * false if the name was never mangled to begin with.
     80    */
     81   static bool Unmangle(std::string* out_name, std::string* out_package) {
     82     size_t pivot = out_name->find('$');
     83     if (pivot == std::string::npos) {
     84       return false;
     85     }
     86 
     87     out_package->assign(out_name->data(), pivot);
     88     std::string new_name = out_name->substr(pivot + 1);
     89     *out_name = std::move(new_name);
     90     return true;
     91   }
     92 
     93  private:
     94   NameManglerPolicy policy_;
     95 };
     96 
     97 }  // namespace aapt
     98 
     99 #endif  // AAPT_NAME_MANGLER_H
    100