• 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 <array>
21 #include <limits>
22 #include <ostream>
23 #include <vector>
24 
25 #include "androidfw/ResourceTypes.h"
26 #include "androidfw/StringPiece.h"
27 
28 #include "Diagnostics.h"
29 #include "Resource.h"
30 #include "StringPool.h"
31 #include "io/File.h"
32 #include "text/Printer.h"
33 #include "util/Maybe.h"
34 
35 namespace aapt {
36 
37 class ValueVisitor;
38 class ConstValueVisitor;
39 
40 // A resource value. This is an all-encompassing representation
41 // of Item and Map and their subclasses. The way to do
42 // type specific operations is to check the Value's type() and
43 // cast it to the appropriate subclass. This isn't super clean,
44 // but it is the simplest strategy.
45 class Value {
46  public:
47   virtual ~Value() = default;
48 
49   // Whether this value is weak and can be overridden without warning or error. Default is false.
IsWeak()50   bool IsWeak() const {
51     return weak_;
52   }
53 
SetWeak(bool val)54   void SetWeak(bool val) {
55     weak_ = val;
56   }
57 
58   // Whether the value is marked as translatable. This does not persist when flattened to binary.
59   // It is only used during compilation phase.
SetTranslatable(bool val)60   void SetTranslatable(bool val) {
61     translatable_ = val;
62   }
63 
64   // Default true.
IsTranslatable()65   bool IsTranslatable() const {
66     return translatable_;
67   }
68 
69   // Returns the source where this value was defined.
GetSource()70   const Source& GetSource() const {
71     return source_;
72   }
73 
SetSource(const Source & source)74   void SetSource(const Source& source) {
75     source_ = source;
76   }
77 
SetSource(Source && source)78   void SetSource(Source&& source) {
79     source_ = std::move(source);
80   }
81 
82   // Returns the comment that was associated with this resource.
GetComment()83   const std::string& GetComment() const {
84     return comment_;
85   }
86 
SetComment(const android::StringPiece & str)87   void SetComment(const android::StringPiece& str) {
88     comment_ = str.to_string();
89   }
90 
SetComment(std::string && str)91   void SetComment(std::string&& str) {
92     comment_ = std::move(str);
93   }
94 
95   virtual bool Equals(const Value* value) const = 0;
96 
97   // Calls the appropriate overload of ValueVisitor.
98   virtual void Accept(ValueVisitor* visitor) = 0;
99 
100   // Calls the appropriate overload of ConstValueVisitor.
101   virtual void Accept(ConstValueVisitor* visitor) const = 0;
102 
103   // Clone the value. `new_pool` is the new StringPool that
104   // any resources with strings should use when copying their string.
105   virtual Value* Clone(StringPool* new_pool) const = 0;
106 
107   // Human readable printout of this value.
108   virtual void Print(std::ostream* out) const = 0;
109 
110   // Human readable printout of this value that may omit some information for the sake
111   // of brevity and readability. Default implementation just calls Print().
112   virtual void PrettyPrint(text::Printer* printer) const;
113 
114   friend std::ostream& operator<<(std::ostream& out, const Value& value);
115 
116  protected:
117   Source source_;
118   std::string comment_;
119   bool weak_ = false;
120   bool translatable_ = true;
121 };
122 
123 // Inherit from this to get visitor accepting implementations for free.
124 template <typename Derived>
125 struct BaseValue : public Value {
126   void Accept(ValueVisitor* visitor) override;
127   void Accept(ConstValueVisitor* visitor) const override;
128 };
129 
130 // A resource item with a single value. This maps to android::ResTable_entry.
131 struct Item : public Value {
132   // Clone the Item.
133   virtual Item* Clone(StringPool* new_pool) const override = 0;
134 
135   // Fills in an android::Res_value structure with this Item's binary representation.
136   // Returns false if an error occurred.
137   virtual bool Flatten(android::Res_value* out_value) const = 0;
138 };
139 
140 // Inherit from this to get visitor accepting implementations for free.
141 template <typename Derived>
142 struct BaseItem : public Item {
143   void Accept(ValueVisitor* visitor) override;
144   void Accept(ConstValueVisitor* visitor) const override;
145 };
146 
147 // A reference to another resource. This maps to android::Res_value::TYPE_REFERENCE.
148 // A reference can be symbolic (with the name set to a valid resource name) or be
149 // numeric (the id is set to a valid resource ID).
150 struct Reference : public BaseItem<Reference> {
151   enum class Type {
152     kResource,
153     kAttribute,
154   };
155 
156   Maybe<ResourceName> name;
157   Maybe<ResourceId> id;
158   Reference::Type reference_type;
159   bool private_reference = false;
160   bool is_dynamic = false;
161 
162   Reference();
163   explicit Reference(const ResourceNameRef& n, Type type = Type::kResource);
164   explicit Reference(const ResourceId& i, Type type = Type::kResource);
165   Reference(const ResourceNameRef& n, const ResourceId& i);
166 
167   bool Equals(const Value* value) const override;
168   bool Flatten(android::Res_value* out_value) const override;
169   Reference* Clone(StringPool* new_pool) const override;
170   void Print(std::ostream* out) const override;
171   void PrettyPrint(text::Printer* printer) const override;
172 
173   // Prints the reference without a package name if the package name matches the one given.
174   void PrettyPrint(const android::StringPiece& package, text::Printer* printer) const;
175 };
176 
177 bool operator<(const Reference&, const Reference&);
178 bool operator==(const Reference&, const Reference&);
179 
180 // An ID resource. Has no real value, just a place holder.
181 struct Id : public BaseItem<Id> {
IdId182   Id() {
183     weak_ = true;
184   }
185 
186   bool Equals(const Value* value) const override;
187   bool Flatten(android::Res_value* out) const override;
188   Id* Clone(StringPool* new_pool) const override;
189   void Print(std::ostream* out) const override;
190 };
191 
192 // A raw, unprocessed string. This may contain quotations, escape sequences, and whitespace.
193 // This shall *NOT* end up in the final resource table.
194 struct RawString : public BaseItem<RawString> {
195   StringPool::Ref value;
196 
197   explicit RawString(const StringPool::Ref& ref);
198 
199   bool Equals(const Value* value) const override;
200   bool Flatten(android::Res_value* out_value) const override;
201   RawString* Clone(StringPool* new_pool) const override;
202   void Print(std::ostream* out) const override;
203 };
204 
205 // Identifies a range of characters in a string that are untranslatable.
206 // These should not be pseudolocalized. The start and end indices are measured in bytes.
207 struct UntranslatableSection {
208   // Start offset inclusive.
209   size_t start;
210 
211   // End offset exclusive.
212   size_t end;
213 };
214 
215 inline bool operator==(const UntranslatableSection& a, const UntranslatableSection& b) {
216   return a.start == b.start && a.end == b.end;
217 }
218 
219 inline bool operator!=(const UntranslatableSection& a, const UntranslatableSection& b) {
220   return a.start != b.start || a.end != b.end;
221 }
222 
223 struct String : public BaseItem<String> {
224   StringPool::Ref value;
225 
226   // Sections of the string to NOT translate. Mainly used
227   // for pseudolocalization. This data is NOT persisted
228   // in any format.
229   std::vector<UntranslatableSection> untranslatable_sections;
230 
231   explicit String(const StringPool::Ref& ref);
232 
233   bool Equals(const Value* value) const override;
234   bool Flatten(android::Res_value* out_value) const override;
235   String* Clone(StringPool* new_pool) const override;
236   void Print(std::ostream* out) const override;
237   void PrettyPrint(text::Printer* printer) const override;
238 };
239 
240 struct StyledString : public BaseItem<StyledString> {
241   StringPool::StyleRef value;
242 
243   // Sections of the string to NOT translate. Mainly used
244   // for pseudolocalization. This data is NOT persisted
245   // in any format.
246   std::vector<UntranslatableSection> untranslatable_sections;
247 
248   explicit StyledString(const StringPool::StyleRef& ref);
249 
250   bool Equals(const Value* value) const override;
251   bool Flatten(android::Res_value* out_value) const override;
252   StyledString* Clone(StringPool* new_pool) const override;
253   void Print(std::ostream* out) const override;
254 };
255 
256 struct FileReference : public BaseItem<FileReference> {
257   StringPool::Ref path;
258 
259   // A handle to the file object from which this file can be read.
260   // This field is NOT persisted in any format. It is transient.
261   io::IFile* file = nullptr;
262 
263   // FileType of the file pointed to by `file`. This is used to know how to inflate the file,
264   // or if to inflate at all (just copy).
265   ResourceFile::Type type = ResourceFile::Type::kUnknown;
266 
267   FileReference() = default;
268   explicit FileReference(const StringPool::Ref& path);
269 
270   bool Equals(const Value* value) const override;
271   bool Flatten(android::Res_value* out_value) const override;
272   FileReference* Clone(StringPool* new_pool) const override;
273   void Print(std::ostream* out) const override;
274 };
275 
276 // Represents any other android::Res_value.
277 struct BinaryPrimitive : public BaseItem<BinaryPrimitive> {
278   android::Res_value value;
279 
280   BinaryPrimitive() = default;
281   explicit BinaryPrimitive(const android::Res_value& val);
282   BinaryPrimitive(uint8_t dataType, uint32_t data);
283 
284   bool Equals(const Value* value) const override;
285   bool Flatten(android::Res_value* out_value) const override;
286   BinaryPrimitive* Clone(StringPool* new_pool) const override;
287   void Print(std::ostream* out) const override;
288   void PrettyPrint(text::Printer* printer) const override;
289 };
290 
291 struct Attribute : public BaseValue<Attribute> {
292   struct Symbol {
293     Reference symbol;
294     uint32_t value;
295 
296     friend std::ostream& operator<<(std::ostream& out, const Symbol& symbol);
297   };
298 
299   uint32_t type_mask;
300   int32_t min_int;
301   int32_t max_int;
302   std::vector<Symbol> symbols;
303 
304   explicit Attribute(uint32_t t = 0u);
305 
306   bool Equals(const Value* value) const override;
307 
308   // Returns true if this Attribute's format is compatible with the given Attribute. The basic
309   // rule is that TYPE_REFERENCE can be ignored for both of the Attributes, and TYPE_FLAGS and
310   // TYPE_ENUMS are never compatible.
311   bool IsCompatibleWith(const Attribute& attr) const;
312 
313   Attribute* Clone(StringPool* new_pool) const override;
314   std::string MaskString() const;
315   void Print(std::ostream* out) const override;
316   bool Matches(const Item& item, DiagMessage* out_msg = nullptr) const;
317 };
318 
319 struct Style : public BaseValue<Style> {
320   struct Entry {
321     Reference key;
322     std::unique_ptr<Item> value;
323 
324     friend std::ostream& operator<<(std::ostream& out, const Entry& entry);
325   };
326 
327   Maybe<Reference> parent;
328 
329   // If set to true, the parent was auto inferred from the style's name.
330   bool parent_inferred = false;
331 
332   std::vector<Entry> entries;
333 
334   bool Equals(const Value* value) const override;
335   Style* Clone(StringPool* new_pool) const override;
336   void Print(std::ostream* out) const override;
337 
338   // Merges `style` into this Style. All identical attributes of `style` take precedence, including
339   // the parent, if there is one.
340   void MergeWith(Style* style, StringPool* pool);
341 };
342 
343 struct Array : public BaseValue<Array> {
344   std::vector<std::unique_ptr<Item>> elements;
345 
346   bool Equals(const Value* value) const override;
347   Array* Clone(StringPool* new_pool) const override;
348   void Print(std::ostream* out) const override;
349 };
350 
351 struct Plural : public BaseValue<Plural> {
352   enum { Zero = 0, One, Two, Few, Many, Other, Count };
353 
354   std::array<std::unique_ptr<Item>, Count> values;
355 
356   bool Equals(const Value* value) const override;
357   Plural* Clone(StringPool* new_pool) const override;
358   void Print(std::ostream* out) const override;
359 };
360 
361 struct Styleable : public BaseValue<Styleable> {
362   std::vector<Reference> entries;
363 
364   bool Equals(const Value* value) const override;
365   Styleable* Clone(StringPool* newPool) const override;
366   void Print(std::ostream* out) const override;
367   void MergeWith(Styleable* styleable);
368 };
369 
370 template <typename T>
371 typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<(
372     std::ostream& out, const std::unique_ptr<T>& value) {
373   if (value == nullptr) {
374     out << "NULL";
375   } else {
376     value->Print(&out);
377   }
378   return out;
379 }
380 
381 }  // namespace aapt
382 
383 #endif  // AAPT_RESOURCE_VALUES_H
384