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