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