1 // 2 // Copyright 2006 The Android Open Source Project 3 // 4 // Build resource files from raw assets. 5 // 6 7 #ifndef RESOURCE_TABLE_H 8 #define RESOURCE_TABLE_H 9 10 #include "StringPool.h" 11 #include "SourcePos.h" 12 13 #include <set> 14 #include <map> 15 16 using namespace std; 17 18 class XMLNode; 19 class ResourceTable; 20 21 enum { 22 XML_COMPILE_STRIP_COMMENTS = 1<<0, 23 XML_COMPILE_ASSIGN_ATTRIBUTE_IDS = 1<<1, 24 XML_COMPILE_COMPACT_WHITESPACE = 1<<2, 25 XML_COMPILE_STRIP_WHITESPACE = 1<<3, 26 XML_COMPILE_STRIP_RAW_VALUES = 1<<4, 27 28 XML_COMPILE_STANDARD_RESOURCE = 29 XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS 30 | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES 31 }; 32 33 status_t compileXmlFile(const sp<AaptAssets>& assets, 34 const sp<AaptFile>& target, 35 ResourceTable* table, 36 int options = XML_COMPILE_STANDARD_RESOURCE); 37 38 status_t compileXmlFile(const sp<AaptAssets>& assets, 39 const sp<XMLNode>& xmlTree, 40 const sp<AaptFile>& target, 41 ResourceTable* table, 42 int options = XML_COMPILE_STANDARD_RESOURCE); 43 44 status_t compileResourceFile(Bundle* bundle, 45 const sp<AaptAssets>& assets, 46 const sp<AaptFile>& in, 47 const ResTable_config& defParams, 48 const bool overwrite, 49 ResourceTable* outTable); 50 51 struct AccessorCookie 52 { 53 SourcePos sourcePos; 54 String8 attr; 55 String8 value; 56 AccessorCookieAccessorCookie57 AccessorCookie(const SourcePos&p, const String8& a, const String8& v) 58 :sourcePos(p), 59 attr(a), 60 value(v) 61 { 62 } 63 }; 64 65 class ResourceTable : public ResTable::Accessor 66 { 67 public: 68 class Package; 69 class Type; 70 class Entry; 71 72 ResourceTable(Bundle* bundle, const String16& assetsPackage); 73 74 status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets); 75 76 status_t addPublic(const SourcePos& pos, 77 const String16& package, 78 const String16& type, 79 const String16& name, 80 const uint32_t ident); 81 82 status_t addEntry(const SourcePos& pos, 83 const String16& package, 84 const String16& type, 85 const String16& name, 86 const String16& value, 87 const Vector<StringPool::entry_style_span>* style = NULL, 88 const ResTable_config* params = NULL, 89 const bool doSetIndex = false, 90 const int32_t format = ResTable_map::TYPE_ANY, 91 const bool overwrite = false); 92 93 status_t startBag(const SourcePos& pos, 94 const String16& package, 95 const String16& type, 96 const String16& name, 97 const String16& bagParent, 98 const ResTable_config* params = NULL, 99 bool overlay = false, 100 bool replace = false, 101 bool isId = false); 102 103 status_t addBag(const SourcePos& pos, 104 const String16& package, 105 const String16& type, 106 const String16& name, 107 const String16& bagParent, 108 const String16& bagKey, 109 const String16& value, 110 const Vector<StringPool::entry_style_span>* style = NULL, 111 const ResTable_config* params = NULL, 112 bool replace = false, 113 bool isId = false, 114 const int32_t format = ResTable_map::TYPE_ANY); 115 116 bool hasBagOrEntry(const String16& package, 117 const String16& type, 118 const String16& name) const; 119 120 bool hasBagOrEntry(const String16& ref, 121 const String16* defType = NULL, 122 const String16* defPackage = NULL); 123 124 bool appendComment(const String16& package, 125 const String16& type, 126 const String16& name, 127 const String16& comment, 128 bool onlyIfEmpty = false); 129 130 bool appendTypeComment(const String16& package, 131 const String16& type, 132 const String16& name, 133 const String16& comment); 134 135 void canAddEntry(const SourcePos& pos, 136 const String16& package, const String16& type, const String16& name); 137 138 size_t size() const; 139 size_t numLocalResources() const; 140 bool hasResources() const; 141 142 sp<AaptFile> flatten(Bundle*); 143 makeResId(uint32_t packageId,uint32_t typeId,uint32_t nameId)144 static inline uint32_t makeResId(uint32_t packageId, 145 uint32_t typeId, 146 uint32_t nameId) 147 { 148 return nameId | (typeId<<16) | (packageId<<24); 149 } 150 151 static inline uint32_t getResId(const sp<Package>& p, 152 const sp<Type>& t, 153 uint32_t nameId); 154 155 uint32_t getResId(const String16& package, 156 const String16& type, 157 const String16& name, 158 bool onlyPublic = false) const; 159 160 uint32_t getResId(const String16& ref, 161 const String16* defType = NULL, 162 const String16* defPackage = NULL, 163 const char** outErrorMsg = NULL, 164 bool onlyPublic = false) const; 165 166 static bool isValidResourceName(const String16& s); 167 168 bool stringToValue(Res_value* outValue, StringPool* pool, 169 const String16& str, 170 bool preserveSpaces, bool coerceType, 171 uint32_t attrID, 172 const Vector<StringPool::entry_style_span>* style = NULL, 173 String16* outStr = NULL, void* accessorCookie = NULL, 174 uint32_t attrType = ResTable_map::TYPE_ANY); 175 176 status_t assignResourceIds(); 177 status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL); 178 void addLocalization(const String16& name, const String8& locale); 179 status_t validateLocalizations(void); 180 181 status_t flatten(Bundle*, const sp<AaptFile>& dest); 182 183 void writePublicDefinitions(const String16& package, FILE* fp); 184 185 virtual uint32_t getCustomResource(const String16& package, 186 const String16& type, 187 const String16& name) const; 188 virtual uint32_t getCustomResourceWithCreation(const String16& package, 189 const String16& type, 190 const String16& name, 191 const bool createIfNeeded); 192 virtual uint32_t getRemappedPackage(uint32_t origPackage) const; 193 virtual bool getAttributeType(uint32_t attrID, uint32_t* outType); 194 virtual bool getAttributeMin(uint32_t attrID, uint32_t* outMin); 195 virtual bool getAttributeMax(uint32_t attrID, uint32_t* outMax); 196 virtual bool getAttributeKeys(uint32_t attrID, Vector<String16>* outKeys); 197 virtual bool getAttributeEnum(uint32_t attrID, 198 const char16_t* name, size_t nameLen, 199 Res_value* outValue); 200 virtual bool getAttributeFlags(uint32_t attrID, 201 const char16_t* name, size_t nameLen, 202 Res_value* outValue); 203 virtual uint32_t getAttributeL10N(uint32_t attrID); 204 205 virtual bool getLocalizationSetting(); 206 virtual void reportError(void* accessorCookie, const char* fmt, ...); 207 setCurrentXmlPos(const SourcePos & pos)208 void setCurrentXmlPos(const SourcePos& pos) { mCurrentXmlPos = pos; } 209 210 class Item { 211 public: Item()212 Item() : isId(false), format(ResTable_map::TYPE_ANY), bagKeyId(0), evaluating(false) 213 { memset(&parsedValue, 0, sizeof(parsedValue)); } 214 Item(const SourcePos& pos, 215 bool _isId, 216 const String16& _value, 217 const Vector<StringPool::entry_style_span>* _style = NULL, 218 int32_t format = ResTable_map::TYPE_ANY); Item(const Item & o)219 Item(const Item& o) : sourcePos(o.sourcePos), 220 isId(o.isId), value(o.value), style(o.style), 221 format(o.format), bagKeyId(o.bagKeyId), evaluating(false) { 222 memset(&parsedValue, 0, sizeof(parsedValue)); 223 } ~Item()224 ~Item() { } 225 226 Item& operator=(const Item& o) { 227 sourcePos = o.sourcePos; 228 isId = o.isId; 229 value = o.value; 230 style = o.style; 231 format = o.format; 232 bagKeyId = o.bagKeyId; 233 parsedValue = o.parsedValue; 234 return *this; 235 } 236 237 SourcePos sourcePos; 238 mutable bool isId; 239 String16 value; 240 Vector<StringPool::entry_style_span> style; 241 int32_t format; 242 uint32_t bagKeyId; 243 mutable bool evaluating; 244 Res_value parsedValue; 245 }; 246 247 class Entry : public RefBase { 248 public: Entry(const String16 & name,const SourcePos & pos)249 Entry(const String16& name, const SourcePos& pos) 250 : mName(name), mType(TYPE_UNKNOWN), 251 mItemFormat(ResTable_map::TYPE_ANY), mNameIndex(-1), mPos(pos) 252 { } ~Entry()253 virtual ~Entry() { } 254 255 enum type { 256 TYPE_UNKNOWN = 0, 257 TYPE_ITEM, 258 TYPE_BAG 259 }; 260 getName()261 String16 getName() const { return mName; } getType()262 type getType() const { return mType; } 263 setParent(const String16 & parent)264 void setParent(const String16& parent) { mParent = parent; } getParent()265 String16 getParent() const { return mParent; } 266 267 status_t makeItABag(const SourcePos& sourcePos); 268 269 status_t emptyBag(const SourcePos& sourcePos); 270 271 status_t setItem(const SourcePos& pos, 272 const String16& value, 273 const Vector<StringPool::entry_style_span>* style = NULL, 274 int32_t format = ResTable_map::TYPE_ANY, 275 const bool overwrite = false); 276 277 status_t addToBag(const SourcePos& pos, 278 const String16& key, const String16& value, 279 const Vector<StringPool::entry_style_span>* style = NULL, 280 bool replace=false, bool isId = false, 281 int32_t format = ResTable_map::TYPE_ANY); 282 283 // Index of the entry's name string in the key pool. getNameIndex()284 int32_t getNameIndex() const { return mNameIndex; } setNameIndex(int32_t index)285 void setNameIndex(int32_t index) { mNameIndex = index; } 286 getItem()287 const Item* getItem() const { return mType == TYPE_ITEM ? &mItem : NULL; } getBag()288 const KeyedVector<String16, Item>& getBag() const { return mBag; } 289 290 status_t generateAttributes(ResourceTable* table, 291 const String16& package); 292 293 status_t assignResourceIds(ResourceTable* table, 294 const String16& package); 295 296 status_t prepareFlatten(StringPool* strings, ResourceTable* table); 297 298 ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic); 299 getPos()300 const SourcePos& getPos() const { return mPos; } 301 302 private: 303 String16 mName; 304 String16 mParent; 305 type mType; 306 Item mItem; 307 int32_t mItemFormat; 308 KeyedVector<String16, Item> mBag; 309 int32_t mNameIndex; 310 uint32_t mParentId; 311 SourcePos mPos; 312 }; 313 314 struct ConfigDescription : public ResTable_config { ConfigDescriptionConfigDescription315 ConfigDescription() { 316 memset(this, 0, sizeof(*this)); 317 size = sizeof(ResTable_config); 318 } ConfigDescriptionConfigDescription319 ConfigDescription(const ResTable_config&o) { 320 *static_cast<ResTable_config*>(this) = o; 321 size = sizeof(ResTable_config); 322 } ConfigDescriptionConfigDescription323 ConfigDescription(const ConfigDescription&o) { 324 *static_cast<ResTable_config*>(this) = o; 325 } 326 327 ConfigDescription& operator=(const ResTable_config& o) { 328 *static_cast<ResTable_config*>(this) = o; 329 size = sizeof(ResTable_config); 330 return *this; 331 } 332 ConfigDescription& operator=(const ConfigDescription& o) { 333 *static_cast<ResTable_config*>(this) = o; 334 return *this; 335 } 336 337 inline bool operator<(const ConfigDescription& o) const { return compare(o) < 0; } 338 inline bool operator<=(const ConfigDescription& o) const { return compare(o) <= 0; } 339 inline bool operator==(const ConfigDescription& o) const { return compare(o) == 0; } 340 inline bool operator!=(const ConfigDescription& o) const { return compare(o) != 0; } 341 inline bool operator>=(const ConfigDescription& o) const { return compare(o) >= 0; } 342 inline bool operator>(const ConfigDescription& o) const { return compare(o) > 0; } 343 }; 344 345 class ConfigList : public RefBase { 346 public: ConfigList(const String16 & name,const SourcePos & pos)347 ConfigList(const String16& name, const SourcePos& pos) 348 : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { } ~ConfigList()349 virtual ~ConfigList() { } 350 getName()351 String16 getName() const { return mName; } getPos()352 const SourcePos& getPos() const { return mPos; } 353 354 void appendComment(const String16& comment, bool onlyIfEmpty = false); getComment()355 const String16& getComment() const { return mComment; } 356 357 void appendTypeComment(const String16& comment); getTypeComment()358 const String16& getTypeComment() const { return mTypeComment; } 359 360 // Index of this entry in its Type. getEntryIndex()361 int32_t getEntryIndex() const { return mEntryIndex; } setEntryIndex(int32_t index)362 void setEntryIndex(int32_t index) { mEntryIndex = index; } 363 setPublic(bool pub)364 void setPublic(bool pub) { mPublic = pub; } getPublic()365 bool getPublic() const { return mPublic; } setPublicSourcePos(const SourcePos & pos)366 void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; } getPublicSourcePos()367 const SourcePos& getPublicSourcePos() { return mPublicSourcePos; } 368 addEntry(const ResTable_config & config,const sp<Entry> & entry)369 void addEntry(const ResTable_config& config, const sp<Entry>& entry) { 370 mEntries.add(config, entry); 371 } 372 getEntries()373 const DefaultKeyedVector<ConfigDescription, sp<Entry> >& getEntries() const { return mEntries; } 374 private: 375 const String16 mName; 376 const SourcePos mPos; 377 String16 mComment; 378 String16 mTypeComment; 379 bool mPublic; 380 SourcePos mPublicSourcePos; 381 int32_t mEntryIndex; 382 DefaultKeyedVector<ConfigDescription, sp<Entry> > mEntries; 383 }; 384 385 class Public { 386 public: Public()387 Public() : sourcePos(), ident(0) { } Public(const SourcePos & pos,const String16 & _comment,uint32_t _ident)388 Public(const SourcePos& pos, 389 const String16& _comment, 390 uint32_t _ident) 391 : sourcePos(pos), 392 comment(_comment), ident(_ident) { } Public(const Public & o)393 Public(const Public& o) : sourcePos(o.sourcePos), 394 comment(o.comment), ident(o.ident) { } ~Public()395 ~Public() { } 396 397 Public& operator=(const Public& o) { 398 sourcePos = o.sourcePos; 399 comment = o.comment; 400 ident = o.ident; 401 return *this; 402 } 403 404 SourcePos sourcePos; 405 String16 comment; 406 uint32_t ident; 407 }; 408 409 class Type : public RefBase { 410 public: Type(const String16 & name,const SourcePos & pos)411 Type(const String16& name, const SourcePos& pos) 412 : mName(name), mFirstPublicSourcePos(NULL), mPublicIndex(-1), mIndex(-1), mPos(pos) 413 { } ~Type()414 virtual ~Type() { delete mFirstPublicSourcePos; } 415 416 status_t addPublic(const SourcePos& pos, 417 const String16& name, 418 const uint32_t ident); 419 420 void canAddEntry(const String16& name); 421 getName()422 String16 getName() const { return mName; } 423 sp<Entry> getEntry(const String16& entry, 424 const SourcePos& pos, 425 const ResTable_config* config = NULL, 426 bool doSetIndex = false, 427 bool overlay = false); 428 getFirstPublicSourcePos()429 const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; } 430 getPublicIndex()431 int32_t getPublicIndex() const { return mPublicIndex; } 432 getIndex()433 int32_t getIndex() const { return mIndex; } setIndex(int32_t index)434 void setIndex(int32_t index) { mIndex = index; } 435 436 status_t applyPublicEntryOrder(); 437 getUniqueConfigs()438 const SortedVector<ConfigDescription>& getUniqueConfigs() const { return mUniqueConfigs; } 439 getConfigs()440 const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; } getOrderedConfigs()441 const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; } 442 getCanAddEntries()443 const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; } 444 getPos()445 const SourcePos& getPos() const { return mPos; } 446 private: 447 String16 mName; 448 SourcePos* mFirstPublicSourcePos; 449 DefaultKeyedVector<String16, Public> mPublic; 450 SortedVector<ConfigDescription> mUniqueConfigs; 451 DefaultKeyedVector<String16, sp<ConfigList> > mConfigs; 452 Vector<sp<ConfigList> > mOrderedConfigs; 453 SortedVector<String16> mCanAddEntries; 454 int32_t mPublicIndex; 455 int32_t mIndex; 456 SourcePos mPos; 457 }; 458 459 class Package : public RefBase { 460 public: 461 Package(const String16& name, ssize_t includedId=-1); ~Package()462 virtual ~Package() { } 463 getName()464 String16 getName() const { return mName; } 465 sp<Type> getType(const String16& type, 466 const SourcePos& pos, 467 bool doSetIndex = false); 468 getAssignedId()469 ssize_t getAssignedId() const { return mIncludedId; } 470 getTypeStrings()471 const ResStringPool& getTypeStrings() const { return mTypeStrings; } indexOfTypeString(const String16 & s)472 uint32_t indexOfTypeString(const String16& s) const { return mTypeStringsMapping.valueFor(s); } getTypeStringsData()473 const sp<AaptFile> getTypeStringsData() const { return mTypeStringsData; } 474 status_t setTypeStrings(const sp<AaptFile>& data); 475 getKeyStrings()476 const ResStringPool& getKeyStrings() const { return mKeyStrings; } indexOfKeyString(const String16 & s)477 uint32_t indexOfKeyString(const String16& s) const { return mKeyStringsMapping.valueFor(s); } getKeyStringsData()478 const sp<AaptFile> getKeyStringsData() const { return mKeyStringsData; } 479 status_t setKeyStrings(const sp<AaptFile>& data); 480 481 status_t applyPublicTypeOrder(); 482 getTypes()483 const DefaultKeyedVector<String16, sp<Type> >& getTypes() const { return mTypes; } getOrderedTypes()484 const Vector<sp<Type> >& getOrderedTypes() const { return mOrderedTypes; } 485 486 private: 487 status_t setStrings(const sp<AaptFile>& data, 488 ResStringPool* strings, 489 DefaultKeyedVector<String16, uint32_t>* mappings); 490 491 const String16 mName; 492 const ssize_t mIncludedId; 493 DefaultKeyedVector<String16, sp<Type> > mTypes; 494 Vector<sp<Type> > mOrderedTypes; 495 sp<AaptFile> mTypeStringsData; 496 sp<AaptFile> mKeyStringsData; 497 ResStringPool mTypeStrings; 498 ResStringPool mKeyStrings; 499 DefaultKeyedVector<String16, uint32_t> mTypeStringsMapping; 500 DefaultKeyedVector<String16, uint32_t> mKeyStringsMapping; 501 }; 502 503 private: 504 void writePublicDefinitions(const String16& package, FILE* fp, bool pub); 505 sp<Package> getPackage(const String16& package); 506 sp<Type> getType(const String16& package, 507 const String16& type, 508 const SourcePos& pos, 509 bool doSetIndex = false); 510 sp<Entry> getEntry(const String16& package, 511 const String16& type, 512 const String16& name, 513 const SourcePos& pos, 514 bool overlay, 515 const ResTable_config* config = NULL, 516 bool doSetIndex = false); 517 sp<const Entry> getEntry(uint32_t resID, 518 const ResTable_config* config = NULL) const; 519 const Item* getItem(uint32_t resID, uint32_t attrID) const; 520 bool getItemValue(uint32_t resID, uint32_t attrID, 521 Res_value* outValue); 522 523 524 String16 mAssetsPackage; 525 sp<AaptAssets> mAssets; 526 DefaultKeyedVector<String16, sp<Package> > mPackages; 527 Vector<sp<Package> > mOrderedPackages; 528 uint32_t mNextPackageId; 529 bool mHaveAppPackage; 530 bool mIsAppPackage; 531 size_t mNumLocal; 532 SourcePos mCurrentXmlPos; 533 Bundle* mBundle; 534 535 // key = string resource name, value = set of locales in which that name is defined 536 map<String16, set<String8> > mLocalizations; 537 }; 538 539 class ResourceFilter 540 { 541 public: ResourceFilter()542 ResourceFilter() : mData(), mContainsPseudo(false) {} 543 status_t parse(const char* arg); 544 bool match(int axis, uint32_t value); 545 bool match(const ResTable_config& config); containsPseudo()546 inline bool containsPseudo() { return mContainsPseudo; } 547 548 private: 549 KeyedVector<int,SortedVector<uint32_t> > mData; 550 bool mContainsPseudo; 551 }; 552 553 554 #endif 555