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 #include "link/Linkers.h"
18
19 #include <algorithm>
20 #include <iterator>
21
22 #include "android-base/logging.h"
23
24 #include "ResourceTable.h"
25
26 namespace aapt {
27
28 template <typename InputContainer, typename OutputIterator, typename Predicate>
move_if(InputContainer & input_container,OutputIterator result,Predicate pred)29 OutputIterator move_if(InputContainer& input_container, OutputIterator result, Predicate pred) {
30 const auto last = input_container.end();
31 auto new_end = std::find_if(input_container.begin(), input_container.end(), pred);
32 if (new_end == last) {
33 return result;
34 }
35
36 *result = std::move(*new_end);
37
38 auto first = new_end;
39 ++first;
40
41 for (; first != last; ++first) {
42 if (bool(pred(*first))) {
43 // We want to move this guy
44 *result = std::move(*first);
45 ++result;
46 } else {
47 // We want to keep this guy, but we will need to move it up the list to
48 // replace missing items.
49 *new_end = std::move(*first);
50 ++new_end;
51 }
52 }
53
54 input_container.erase(new_end, last);
55 return result;
56 }
57
Consume(IAaptContext * context,ResourceTable * table)58 bool PrivateAttributeMover::Consume(IAaptContext* context, ResourceTable* table) {
59 for (auto& package : table->packages) {
60 ResourceTableType* type = package->FindType(ResourceType::kAttr);
61 if (!type) {
62 continue;
63 }
64
65 if (type->visibility_level != Visibility::Level::kPublic) {
66 // No public attributes, so we can safely leave these private attributes
67 // where they are.
68 continue;
69 }
70
71 std::vector<std::unique_ptr<ResourceEntry>> private_attr_entries;
72
73 move_if(type->entries, std::back_inserter(private_attr_entries),
74 [](const std::unique_ptr<ResourceEntry>& entry) -> bool {
75 return entry->visibility.level != Visibility::Level::kPublic;
76 });
77
78 if (private_attr_entries.empty()) {
79 // No private attributes.
80 continue;
81 }
82
83 ResourceTableType* priv_attr_type = package->FindOrCreateType(ResourceType::kAttrPrivate);
84 CHECK(priv_attr_type->entries.empty());
85 priv_attr_type->entries = std::move(private_attr_entries);
86 }
87 return true;
88 }
89
90 } // namespace aapt
91