• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_RESOURCE_VALUES_H
18 #define AAPT_RESOURCE_VALUES_H
19 
20 #include "Diagnostics.h"
21 #include "Resource.h"
22 #include "StringPool.h"
23 #include "io/File.h"
24 #include "util/Maybe.h"
25 
26 #include <array>
27 #include <androidfw/ResourceTypes.h>
28 #include <ostream>
29 #include <vector>
30 
31 namespace aapt {
32 
33 struct RawValueVisitor;
34 
35 /**
36  * A resource value. This is an all-encompassing representation
37  * of Item and Map and their subclasses. The way to do
38  * type specific operations is to check the Value's type() and
39  * cast it to the appropriate subclass. This isn't super clean,
40  * but it is the simplest strategy.
41  */
42 struct Value {
43 	virtual ~Value() = default;
44 
45     /**
46      * Whether this value is weak and can be overridden without
47      * warning or error. Default is false.
48      */
isWeakValue49     bool isWeak() const {
50         return mWeak;
51     }
52 
setWeakValue53     void setWeak(bool val) {
54         mWeak = val;
55     }
56 
57     /**
58      * Returns the source where this value was defined.
59      */
getSourceValue60     const Source& getSource() const {
61         return mSource;
62     }
63 
setSourceValue64     void setSource(const Source& source) {
65         mSource = source;
66     }
67 
setSourceValue68     void setSource(Source&& source) {
69         mSource = std::move(source);
70     }
71 
72     /**
73      * Returns the comment that was associated with this resource.
74      */
getCommentValue75     StringPiece16 getComment() const {
76         return mComment;
77     }
78 
setCommentValue79     void setComment(const StringPiece16& str) {
80         mComment = str.toString();
81     }
82 
setCommentValue83     void setComment(std::u16string&& str) {
84         mComment = std::move(str);
85     }
86 
87     /**
88      * Calls the appropriate overload of ValueVisitor.
89      */
90     virtual void accept(RawValueVisitor* visitor) = 0;
91 
92     /**
93      * Clone the value.
94      */
95     virtual Value* clone(StringPool* newPool) const = 0;
96 
97     /**
98      * Human readable printout of this value.
99      */
100     virtual void print(std::ostream* out) const = 0;
101 
102 protected:
103     Source mSource;
104     std::u16string mComment;
105     bool mWeak = false;
106 };
107 
108 /**
109  * Inherit from this to get visitor accepting implementations for free.
110  */
111 template <typename Derived>
112 struct BaseValue : public Value {
113     void accept(RawValueVisitor* visitor) override;
114 };
115 
116 /**
117  * A resource item with a single value. This maps to android::ResTable_entry.
118  */
119 struct Item : public Value {
120     /**
121      * Clone the Item.
122      */
123     virtual Item* clone(StringPool* newPool) const override = 0;
124 
125     /**
126      * Fills in an android::Res_value structure with this Item's binary representation.
127      * Returns false if an error occurred.
128      */
129     virtual bool flatten(android::Res_value* outValue) const = 0;
130 };
131 
132 /**
133  * Inherit from this to get visitor accepting implementations for free.
134  */
135 template <typename Derived>
136 struct BaseItem : public Item {
137     void accept(RawValueVisitor* visitor) override;
138 };
139 
140 /**
141  * A reference to another resource. This maps to android::Res_value::TYPE_REFERENCE.
142  *
143  * A reference can be symbolic (with the name set to a valid resource name) or be
144  * numeric (the id is set to a valid resource ID).
145  */
146 struct Reference : public BaseItem<Reference> {
147     enum class Type {
148         kResource,
149         kAttribute,
150     };
151 
152     Maybe<ResourceName> name;
153     Maybe<ResourceId> id;
154     Reference::Type referenceType;
155     bool privateReference = false;
156 
157     Reference();
158     explicit Reference(const ResourceNameRef& n, Type type = Type::kResource);
159     explicit Reference(const ResourceId& i, Type type = Type::kResource);
160 
161     bool flatten(android::Res_value* outValue) const override;
162     Reference* clone(StringPool* newPool) const override;
163     void print(std::ostream* out) const override;
164 };
165 
166 /**
167  * An ID resource. Has no real value, just a place holder.
168  */
169 struct Id : public BaseItem<Id> {
IdId170     Id() { mWeak = true; }
171     bool flatten(android::Res_value* out) const override;
172     Id* clone(StringPool* newPool) const override;
173     void print(std::ostream* out) const override;
174 };
175 
176 /**
177  * A raw, unprocessed string. This may contain quotations,
178  * escape sequences, and whitespace. This shall *NOT*
179  * end up in the final resource table.
180  */
181 struct RawString : public BaseItem<RawString> {
182     StringPool::Ref value;
183 
184     RawString(const StringPool::Ref& ref);
185 
186     bool flatten(android::Res_value* outValue) const override;
187     RawString* clone(StringPool* newPool) const override;
188     void print(std::ostream* out) const override;
189 };
190 
191 struct String : public BaseItem<String> {
192     StringPool::Ref value;
193 
194     String(const StringPool::Ref& ref);
195 
196     // Whether the string is marked as translateable. This does not persist when flattened.
197     // It is only used during compilation phase.
198     void setTranslateable(bool val);
199     bool isTranslateable() const;
200 
201     bool flatten(android::Res_value* outValue) const override;
202     String* clone(StringPool* newPool) const override;
203     void print(std::ostream* out) const override;
204 
205 private:
206     bool mTranslateable;
207 };
208 
209 struct StyledString : public BaseItem<StyledString> {
210     StringPool::StyleRef value;
211 
212     StyledString(const StringPool::StyleRef& ref);
213 
214     // Whether the string is marked as translateable. This does not persist when flattened.
215     // It is only used during compilation phase.
216     void setTranslateable(bool val);
217     bool isTranslateable() const;
218 
219     bool flatten(android::Res_value* outValue) const override;
220     StyledString* clone(StringPool* newPool) const override;
221     void print(std::ostream* out) const override;
222 
223 private:
224     bool mTranslateable;
225 };
226 
227 struct FileReference : public BaseItem<FileReference> {
228     StringPool::Ref path;
229 
230     /**
231      * A handle to the file object from which this file can be read.
232      */
233     io::IFile* file = nullptr;
234 
235     FileReference() = default;
236     FileReference(const StringPool::Ref& path);
237 
238     bool flatten(android::Res_value* outValue) const override;
239     FileReference* clone(StringPool* newPool) const override;
240     void print(std::ostream* out) const override;
241 };
242 
243 /**
244  * Represents any other android::Res_value.
245  */
246 struct BinaryPrimitive : public BaseItem<BinaryPrimitive> {
247     android::Res_value value;
248 
249     BinaryPrimitive() = default;
250     BinaryPrimitive(const android::Res_value& val);
251     BinaryPrimitive(uint8_t dataType, uint32_t data);
252 
253     bool flatten(android::Res_value* outValue) const override;
254     BinaryPrimitive* clone(StringPool* newPool) const override;
255     void print(std::ostream* out) const override;
256 };
257 
258 struct Attribute : public BaseValue<Attribute> {
259     struct Symbol {
260         Reference symbol;
261         uint32_t value;
262     };
263 
264     uint32_t typeMask;
265     int32_t minInt;
266     int32_t maxInt;
267     std::vector<Symbol> symbols;
268 
269     Attribute(bool w, uint32_t t = 0u);
270 
271     Attribute* clone(StringPool* newPool) const override;
272     void printMask(std::ostream* out) const;
273     void print(std::ostream* out) const override;
274     bool matches(const Item* item, DiagMessage* outMsg) const;
275 };
276 
277 struct Style : public BaseValue<Style> {
278     struct Entry {
279         Reference key;
280         std::unique_ptr<Item> value;
281     };
282 
283     Maybe<Reference> parent;
284 
285     /**
286      * If set to true, the parent was auto inferred from the
287      * style's name.
288      */
289     bool parentInferred = false;
290 
291     std::vector<Entry> entries;
292 
293     Style* clone(StringPool* newPool) const override;
294     void print(std::ostream* out) const override;
295 };
296 
297 struct Array : public BaseValue<Array> {
298     std::vector<std::unique_ptr<Item>> items;
299 
300     Array* clone(StringPool* newPool) const override;
301     void print(std::ostream* out) const override;
302 };
303 
304 struct Plural : public BaseValue<Plural> {
305     enum {
306         Zero = 0,
307         One,
308         Two,
309         Few,
310         Many,
311         Other,
312         Count
313     };
314 
315     std::array<std::unique_ptr<Item>, Count> values;
316 
317     Plural* clone(StringPool* newPool) const override;
318     void print(std::ostream* out) const override;
319 };
320 
321 struct Styleable : public BaseValue<Styleable> {
322     std::vector<Reference> entries;
323 
324     Styleable* clone(StringPool* newPool) const override;
325     void print(std::ostream* out) const override;
326 };
327 
328 /**
329  * Stream operator for printing Value objects.
330  */
331 inline ::std::ostream& operator<<(::std::ostream& out, const Value& value) {
332     value.print(&out);
333     return out;
334 }
335 
336 inline ::std::ostream& operator<<(::std::ostream& out, const Attribute::Symbol& s) {
337     if (s.symbol.name) {
338         out << s.symbol.name.value().entry;
339     } else {
340         out << "???";
341     }
342     return out << "=" << s.value;
343 }
344 
345 } // namespace aapt
346 
347 #endif // AAPT_RESOURCE_VALUES_H
348