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