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 <map>
11  #include <queue>
12  #include <set>
13  
14  #include "ConfigDescription.h"
15  #include "ResourceFilter.h"
16  #include "SourcePos.h"
17  #include "StringPool.h"
18  #include "Symbol.h"
19  
20  class XMLNode;
21  class ResourceTable;
22  
23  enum {
24      XML_COMPILE_STRIP_COMMENTS = 1<<0,
25      XML_COMPILE_ASSIGN_ATTRIBUTE_IDS = 1<<1,
26      XML_COMPILE_PARSE_VALUES = 1 << 2,
27      XML_COMPILE_COMPACT_WHITESPACE = 1<<3,
28      XML_COMPILE_STRIP_WHITESPACE = 1<<4,
29      XML_COMPILE_STRIP_RAW_VALUES = 1<<5,
30      XML_COMPILE_UTF8 = 1<<6,
31  
32      XML_COMPILE_STANDARD_RESOURCE =
33              XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS | XML_COMPILE_PARSE_VALUES
34              | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES
35  };
36  
37  status_t compileXmlFile(const Bundle* bundle,
38                          const sp<AaptAssets>& assets,
39                          const String16& resourceName,
40                          const sp<AaptFile>& target,
41                          ResourceTable* table,
42                          int options = XML_COMPILE_STANDARD_RESOURCE);
43  
44  status_t compileXmlFile(const Bundle* bundle,
45                          const sp<AaptAssets>& assets,
46                          const String16& resourceName,
47                          const sp<AaptFile>& target,
48                          const sp<AaptFile>& outTarget,
49                          ResourceTable* table,
50                          int options = XML_COMPILE_STANDARD_RESOURCE);
51  
52  status_t compileXmlFile(const Bundle* bundle,
53                          const sp<AaptAssets>& assets,
54                          const String16& resourceName,
55                          const sp<XMLNode>& xmlTree,
56                          const sp<AaptFile>& target,
57                          ResourceTable* table,
58                          int options = XML_COMPILE_STANDARD_RESOURCE);
59  
60  status_t compileResourceFile(Bundle* bundle,
61                               const sp<AaptAssets>& assets,
62                               const sp<AaptFile>& in,
63                               const ResTable_config& defParams,
64                               const bool overwrite,
65                               ResourceTable* outTable);
66  
67  struct AccessorCookie
68  {
69      SourcePos sourcePos;
70      String8 attr;
71      String8 value;
72  
AccessorCookieAccessorCookie73      AccessorCookie(const SourcePos&p, const String8& a, const String8& v)
74          :sourcePos(p),
75           attr(a),
76           value(v)
77      {
78      }
79  };
80  
81  // Holds the necessary information to compile the
82  // resource.
83  struct CompileResourceWorkItem {
84      String16 resourceName;
85      String8 resPath;
86      sp<AaptFile> file;
87      sp<XMLNode> xmlRoot;
88      bool needsCompiling = true;
89  };
90  
91  class ResourceTable : public ResTable::Accessor
92  {
93  public:
94      // The type of package to build.
95      enum PackageType {
96          App,
97          System,
98          SharedLibrary,
99          AppFeature
100      };
101  
102      class Package;
103      class Type;
104      class Entry;
105      class ConfigList;
106  
107      /**
108       * Exposed for testing. Determines whether a versioned resource should be generated
109       * based on the other available configurations for that resource.
110       */
111      static bool shouldGenerateVersionedResource(const sp<ConfigList>& configList,
112                                                  const ConfigDescription& sourceConfig,
113                                                  const int sdkVersionToGenerate);
114  
115      ResourceTable(Bundle* bundle, const String16& assetsPackage, PackageType type);
116  
getAssetsPackage()117      const String16& getAssetsPackage() const {
118          return mAssetsPackage;
119      }
120  
121      /**
122       * Returns the queue of resources that need to be compiled.
123       * This is only used for resources that have been generated
124       * during the compilation phase. If they were just added
125       * to the AaptAssets, then they may be skipped over
126       * and would mess up iteration order for the existing
127       * resources.
128       */
getWorkQueue()129      std::queue<CompileResourceWorkItem>& getWorkQueue() {
130          return mWorkQueue;
131      }
132  
133      status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets);
134  
135      status_t addPublic(const SourcePos& pos,
136                         const String16& package,
137                         const String16& type,
138                         const String16& name,
139                         const uint32_t ident);
140  
141      status_t addEntry(const SourcePos& pos,
142                        const String16& package,
143                        const String16& type,
144                        const String16& name,
145                        const String16& value,
146                        const Vector<StringPool::entry_style_span>* style = NULL,
147                        const ResTable_config* params = NULL,
148                        const bool doSetIndex = false,
149                        const int32_t format = ResTable_map::TYPE_ANY,
150                        const bool overwrite = false);
151  
152      status_t startBag(const SourcePos& pos,
153                      const String16& package,
154                      const String16& type,
155                      const String16& name,
156                      const String16& bagParent,
157                      const ResTable_config* params = NULL,
158                      bool overlay = false,
159                      bool replace = false,
160                      bool isId = false);
161  
162      status_t addBag(const SourcePos& pos,
163                      const String16& package,
164                      const String16& type,
165                      const String16& name,
166                      const String16& bagParent,
167                      const String16& bagKey,
168                      const String16& value,
169                      const Vector<StringPool::entry_style_span>* style = NULL,
170                      const ResTable_config* params = NULL,
171                      bool replace = false,
172                      bool isId = false,
173                      const int32_t format = ResTable_map::TYPE_ANY);
174  
175      bool hasBagOrEntry(const String16& package,
176                         const String16& type,
177                         const String16& name) const;
178  
179      bool hasBagOrEntry(const String16& package,
180                         const String16& type,
181                         const String16& name,
182                         const ResTable_config& config) const;
183  
184      bool hasBagOrEntry(const String16& ref,
185                         const String16* defType = NULL,
186                         const String16* defPackage = NULL);
187  
188      bool appendComment(const String16& package,
189                         const String16& type,
190                         const String16& name,
191                         const String16& comment,
192                         bool onlyIfEmpty = false);
193  
194      bool appendTypeComment(const String16& package,
195                             const String16& type,
196                             const String16& name,
197                             const String16& comment);
198  
199      void canAddEntry(const SourcePos& pos,
200          const String16& package, const String16& type, const String16& name);
201  
202      size_t size() const;
203      size_t numLocalResources() const;
204      bool hasResources() const;
205  
206      bool versionForCompat(const Bundle* bundle, const String16& resourceName,
207                            const sp<AaptFile>& file, const sp<XMLNode>& root);
208  
209      status_t modifyForCompat(const Bundle* bundle);
210      status_t modifyForCompat(const Bundle* bundle,
211                               const String16& resourceName,
212                               const sp<AaptFile>& file,
213                               const sp<XMLNode>& root);
214  
215      status_t processBundleFormat(const Bundle* bundle,
216                                   const String16& resourceName,
217                                   const sp<AaptFile>& file,
218                                   const sp<XMLNode>& parent);
219  
220  
221      sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
222              const bool isBase);
223  
makeResId(uint32_t packageId,uint32_t typeId,uint32_t nameId)224      static inline uint32_t makeResId(uint32_t packageId,
225                                       uint32_t typeId,
226                                       uint32_t nameId)
227      {
228          return nameId | (typeId<<16) | (packageId<<24);
229      }
230  
231      static inline uint32_t getResId(const sp<Package>& p,
232                                      const sp<Type>& t,
233                                      uint32_t nameId);
234  
235      uint32_t getResId(const String16& package,
236                        const String16& type,
237                        const String16& name,
238                        bool onlyPublic = true) const;
239  
240      uint32_t getResId(const String16& ref,
241                        const String16* defType = NULL,
242                        const String16* defPackage = NULL,
243                        const char** outErrorMsg = NULL,
244                        bool onlyPublic = true) const;
245  
246      static bool isValidResourceName(const String16& s);
247  
248      bool stringToValue(Res_value* outValue, StringPool* pool,
249                         const String16& str,
250                         bool preserveSpaces, bool coerceType,
251                         uint32_t attrID,
252                         const Vector<StringPool::entry_style_span>* style = NULL,
253                         String16* outStr = NULL, void* accessorCookie = NULL,
254                         uint32_t attrType = ResTable_map::TYPE_ANY,
255                         const String8* configTypeName = NULL,
256                         const ConfigDescription* config = NULL);
257  
258      status_t assignResourceIds();
259      status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL,
260                          bool skipSymbolsWithoutDefaultLocalization = false);
261      void addLocalization(const String16& name, const String8& locale, const SourcePos& src);
262      void addDefaultLocalization(const String16& name);
263      status_t validateLocalizations(void);
264  
265      status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
266              const sp<AaptFile>& dest, const bool isBase);
267      status_t flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs);
268  
269      void writePublicDefinitions(const String16& package, FILE* fp);
270  
271      virtual uint32_t getCustomResource(const String16& package,
272                                         const String16& type,
273                                         const String16& name) const;
274      virtual uint32_t getCustomResourceWithCreation(const String16& package,
275                                                     const String16& type,
276                                                     const String16& name,
277                                                     const bool createIfNeeded);
278      virtual uint32_t getRemappedPackage(uint32_t origPackage) const;
279      virtual bool getAttributeType(uint32_t attrID, uint32_t* outType);
280      virtual bool getAttributeMin(uint32_t attrID, uint32_t* outMin);
281      virtual bool getAttributeMax(uint32_t attrID, uint32_t* outMax);
282      virtual bool getAttributeKeys(uint32_t attrID, Vector<String16>* outKeys);
283      virtual bool getAttributeEnum(uint32_t attrID,
284                                    const char16_t* name, size_t nameLen,
285                                    Res_value* outValue);
286      virtual bool getAttributeFlags(uint32_t attrID,
287                                     const char16_t* name, size_t nameLen,
288                                     Res_value* outValue);
289      virtual uint32_t getAttributeL10N(uint32_t attrID);
290  
291      virtual bool getLocalizationSetting();
292      virtual void reportError(void* accessorCookie, const char* fmt, ...);
293  
setCurrentXmlPos(const SourcePos & pos)294      void setCurrentXmlPos(const SourcePos& pos) { mCurrentXmlPos = pos; }
295  
296      class Item {
297      public:
Item()298          Item() : isId(false), format(ResTable_map::TYPE_ANY), bagKeyId(0), evaluating(false)
299              { memset(&parsedValue, 0, sizeof(parsedValue)); }
300          Item(const SourcePos& pos,
301               bool _isId,
302               const String16& _value,
303               const Vector<StringPool::entry_style_span>* _style = NULL,
304               int32_t format = ResTable_map::TYPE_ANY);
Item(const Item & o)305          Item(const Item& o) : sourcePos(o.sourcePos),
306              isId(o.isId), value(o.value), style(o.style),
307              format(o.format), bagKeyId(o.bagKeyId), evaluating(false) {
308              memset(&parsedValue, 0, sizeof(parsedValue));
309          }
~Item()310          ~Item() { }
311  
312          Item& operator=(const Item& o) {
313              sourcePos = o.sourcePos;
314              isId = o.isId;
315              value = o.value;
316              style = o.style;
317              format = o.format;
318              bagKeyId = o.bagKeyId;
319              parsedValue = o.parsedValue;
320              return *this;
321          }
322  
323          SourcePos                               sourcePos;
324          mutable bool                            isId;
325          String16                                value;
326          Vector<StringPool::entry_style_span>    style;
327          int32_t                                 format;
328          uint32_t                                bagKeyId;
329          mutable bool                            evaluating;
330          Res_value                               parsedValue;
331      };
332  
333      class Entry : public RefBase {
334      public:
Entry(const String16 & name,const SourcePos & pos)335          Entry(const String16& name, const SourcePos& pos)
336              : mName(name), mType(TYPE_UNKNOWN),
337                mItemFormat(ResTable_map::TYPE_ANY), mNameIndex(-1), mPos(pos)
338          { }
339  
340          Entry(const Entry& entry);
341          Entry& operator=(const Entry& entry);
342  
~Entry()343          virtual ~Entry() { }
344  
345          enum type {
346              TYPE_UNKNOWN = 0,
347              TYPE_ITEM,
348              TYPE_BAG
349          };
350  
getName()351          String16 getName() const { return mName; }
getType()352          type getType() const { return mType; }
353  
setParent(const String16 & parent)354          void setParent(const String16& parent) { mParent = parent; }
getParent()355          String16 getParent() const { return mParent; }
356  
357          status_t makeItABag(const SourcePos& sourcePos);
358  
359          status_t emptyBag(const SourcePos& sourcePos);
360  
361          status_t setItem(const SourcePos& pos,
362                           const String16& value,
363                           const Vector<StringPool::entry_style_span>* style = NULL,
364                           int32_t format = ResTable_map::TYPE_ANY,
365                           const bool overwrite = false);
366  
367          status_t addToBag(const SourcePos& pos,
368                            const String16& key, const String16& value,
369                            const Vector<StringPool::entry_style_span>* style = NULL,
370                            bool replace=false, bool isId = false,
371                            int32_t format = ResTable_map::TYPE_ANY);
372  
373          status_t removeFromBag(const String16& key);
374  
375          // Index of the entry's name string in the key pool.
getNameIndex()376          int32_t getNameIndex() const { return mNameIndex; }
setNameIndex(int32_t index)377          void setNameIndex(int32_t index) { mNameIndex = index; }
378  
getItem()379          const Item* getItem() const { return mType == TYPE_ITEM ? &mItem : NULL; }
getBag()380          const KeyedVector<String16, Item>& getBag() const { return mBag; }
381  
382          status_t generateAttributes(ResourceTable* table,
383                                      const String16& package);
384  
385          status_t assignResourceIds(ResourceTable* table,
386                                     const String16& package);
387  
388          status_t prepareFlatten(StringPool* strings, ResourceTable* table,
389                 const String8* configTypeName, const ConfigDescription* config);
390  
391          status_t remapStringValue(StringPool* strings);
392  
393          ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic);
394  
getPos()395          const SourcePos& getPos() const { return mPos; }
396  
397      private:
398          String16 mName;
399          String16 mParent;
400          type mType;
401          Item mItem;
402          int32_t mItemFormat;
403          KeyedVector<String16, Item> mBag;
404          int32_t mNameIndex;
405          uint32_t mParentId;
406          SourcePos mPos;
407      };
408  
409      class ConfigList : public RefBase {
410      public:
ConfigList(const String16 & name,const SourcePos & pos)411          ConfigList(const String16& name, const SourcePos& pos)
412              : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { }
~ConfigList()413          virtual ~ConfigList() { }
414  
getName()415          String16 getName() const { return mName; }
getPos()416          const SourcePos& getPos() const { return mPos; }
417  
418          void appendComment(const String16& comment, bool onlyIfEmpty = false);
getComment()419          const String16& getComment() const { return mComment; }
420  
421          void appendTypeComment(const String16& comment);
getTypeComment()422          const String16& getTypeComment() const { return mTypeComment; }
423  
424          // Index of this entry in its Type.
getEntryIndex()425          int32_t getEntryIndex() const { return mEntryIndex; }
setEntryIndex(int32_t index)426          void setEntryIndex(int32_t index) { mEntryIndex = index; }
427  
setPublic(bool pub)428          void setPublic(bool pub) { mPublic = pub; }
getPublic()429          bool getPublic() const { return mPublic; }
setPublicSourcePos(const SourcePos & pos)430          void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; }
getPublicSourcePos()431          const SourcePos& getPublicSourcePos() { return mPublicSourcePos; }
432  
addEntry(const ResTable_config & config,const sp<Entry> & entry)433          void addEntry(const ResTable_config& config, const sp<Entry>& entry) {
434              mEntries.add(config, entry);
435          }
436  
removeEntry(const ResTable_config & config)437          void removeEntry(const ResTable_config& config) {
438              mEntries.removeItem(config);
439          }
440  
getEntries()441          const DefaultKeyedVector<ConfigDescription, sp<Entry> >& getEntries() const { return mEntries; }
442      private:
443          const String16 mName;
444          const SourcePos mPos;
445          String16 mComment;
446          String16 mTypeComment;
447          bool mPublic;
448          SourcePos mPublicSourcePos;
449          int32_t mEntryIndex;
450          DefaultKeyedVector<ConfigDescription, sp<Entry> > mEntries;
451      };
452  
453      class Public {
454      public:
Public()455          Public() : sourcePos(), ident(0) { }
Public(const SourcePos & pos,const String16 & _comment,uint32_t _ident)456          Public(const SourcePos& pos,
457                 const String16& _comment,
458                 uint32_t _ident)
459              : sourcePos(pos),
460              comment(_comment), ident(_ident) { }
Public(const Public & o)461          Public(const Public& o) : sourcePos(o.sourcePos),
462              comment(o.comment), ident(o.ident) { }
~Public()463          ~Public() { }
464  
465          Public& operator=(const Public& o) {
466              sourcePos = o.sourcePos;
467              comment = o.comment;
468              ident = o.ident;
469              return *this;
470          }
471  
472          SourcePos   sourcePos;
473          String16    comment;
474          uint32_t    ident;
475      };
476  
477      class Type : public RefBase {
478      public:
Type(const String16 & name,const SourcePos & pos)479          Type(const String16& name, const SourcePos& pos)
480                  : mName(name), mFirstPublicSourcePos(NULL), mPublicIndex(-1), mIndex(-1), mPos(pos)
481          { }
~Type()482          virtual ~Type() { delete mFirstPublicSourcePos; }
483  
484          status_t addPublic(const SourcePos& pos,
485                             const String16& name,
486                             const uint32_t ident);
487  
488          void canAddEntry(const String16& name);
489  
getName()490          String16 getName() const { return mName; }
491          sp<Entry> getEntry(const String16& entry,
492                             const SourcePos& pos,
493                             const ResTable_config* config = NULL,
494                             bool doSetIndex = false,
495                             bool overlay = false,
496                             bool autoAddOverlay = false);
497  
isPublic(const String16 & entry)498          bool isPublic(const String16& entry) const {
499              return mPublic.indexOfKey(entry) >= 0;
500          }
501  
502          sp<ConfigList> removeEntry(const String16& entry);
503  
504          SortedVector<ConfigDescription> getUniqueConfigs() const;
505  
getFirstPublicSourcePos()506          const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; }
507  
getPublicIndex()508          int32_t getPublicIndex() const { return mPublicIndex; }
509  
getIndex()510          int32_t getIndex() const { return mIndex; }
setIndex(int32_t index)511          void setIndex(int32_t index) { mIndex = index; }
512  
513          status_t applyPublicEntryOrder();
514  
getConfigs()515          const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; }
getOrderedConfigs()516          const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; }
getCanAddEntries()517          const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; }
518  
getPos()519          const SourcePos& getPos() const { return mPos; }
520  
521      private:
522          String16 mName;
523          SourcePos* mFirstPublicSourcePos;
524          DefaultKeyedVector<String16, Public> mPublic;
525          DefaultKeyedVector<String16, sp<ConfigList> > mConfigs;
526          Vector<sp<ConfigList> > mOrderedConfigs;
527          SortedVector<String16> mCanAddEntries;
528          int32_t mPublicIndex;
529          int32_t mIndex;
530          SourcePos mPos;
531      };
532  
533      class Package : public RefBase {
534      public:
535          Package(const String16& name, size_t packageId);
~Package()536          virtual ~Package() { }
537  
getName()538          String16 getName() const { return mName; }
539          sp<Type> getType(const String16& type,
540                           const SourcePos& pos,
541                           bool doSetIndex = false);
542  
getAssignedId()543          size_t getAssignedId() const { return mPackageId; }
544  
getTypeStrings()545          const ResStringPool& getTypeStrings() const { return mTypeStrings; }
indexOfTypeString(const String16 & s)546          uint32_t indexOfTypeString(const String16& s) const { return mTypeStringsMapping.valueFor(s); }
getTypeStringsData()547          const sp<AaptFile> getTypeStringsData() const { return mTypeStringsData; }
548          status_t setTypeStrings(const sp<AaptFile>& data);
549  
getKeyStrings()550          const ResStringPool& getKeyStrings() const { return mKeyStrings; }
indexOfKeyString(const String16 & s)551          uint32_t indexOfKeyString(const String16& s) const { return mKeyStringsMapping.valueFor(s); }
getKeyStringsData()552          const sp<AaptFile> getKeyStringsData() const { return mKeyStringsData; }
553          status_t setKeyStrings(const sp<AaptFile>& data);
554  
555          status_t applyPublicTypeOrder();
556  
getTypes()557          const DefaultKeyedVector<String16, sp<Type> >& getTypes() const { return mTypes; }
getOrderedTypes()558          const Vector<sp<Type> >& getOrderedTypes() const { return mOrderedTypes; }
559  
560          void movePrivateAttrs();
561  
562      private:
563          status_t setStrings(const sp<AaptFile>& data,
564                              ResStringPool* strings,
565                              DefaultKeyedVector<String16, uint32_t>* mappings);
566  
567          const String16 mName;
568          const size_t mPackageId;
569          DefaultKeyedVector<String16, sp<Type> > mTypes;
570          Vector<sp<Type> > mOrderedTypes;
571          sp<AaptFile> mTypeStringsData;
572          sp<AaptFile> mKeyStringsData;
573          ResStringPool mTypeStrings;
574          ResStringPool mKeyStrings;
575          DefaultKeyedVector<String16, uint32_t> mTypeStringsMapping;
576          DefaultKeyedVector<String16, uint32_t> mKeyStringsMapping;
577      };
578  
579      void getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources);
580  
581      /**
582       * Make an attribute with the specified format. If another attribute with the same name but
583       * different format exists, this method returns false. If the name is not taken, or if the
584       * format is identical, this returns true.
585       */
586      bool makeAttribute(const String16& package,
587                         const String16& name,
588                         const SourcePos& source,
589                         int32_t format,
590                         const String16& comment,
591                         bool appendComment);
592  
593      sp<Package> getPackage(const String16& package);
594  
595  private:
596      void writePublicDefinitions(const String16& package, FILE* fp, bool pub);
597      sp<Type> getType(const String16& package,
598                       const String16& type,
599                       const SourcePos& pos,
600                       bool doSetIndex = false);
601      sp<Entry> getEntry(const String16& package,
602                         const String16& type,
603                         const String16& name,
604                         const SourcePos& pos,
605                         bool overlay,
606                         const ResTable_config* config = NULL,
607                         bool doSetIndex = false);
608      sp<const Entry> getEntry(uint32_t resID,
609                               const ResTable_config* config = NULL) const;
610      sp<ConfigList> getConfigList(const String16& package,
611                                   const String16& type,
612                                   const String16& name) const;
613      const Item* getItem(uint32_t resID, uint32_t attrID) const;
614      bool getItemValue(uint32_t resID, uint32_t attrID,
615                        Res_value* outValue);
616      int getPublicAttributeSdkLevel(uint32_t attrId) const;
617  
618      status_t processBundleFormatImpl(const Bundle* bundle,
619                                       const String16& resourceName,
620                                       const sp<AaptFile>& file,
621                                       const sp<XMLNode>& parent,
622                                       Vector<sp<XMLNode> >* namespaces);
623  
624      String16 mAssetsPackage;
625      PackageType mPackageType;
626      sp<AaptAssets> mAssets;
627      uint32_t mTypeIdOffset;
628      DefaultKeyedVector<String16, sp<Package> > mPackages;
629      Vector<sp<Package> > mOrderedPackages;
630      size_t mNumLocal;
631      SourcePos mCurrentXmlPos;
632      Bundle* mBundle;
633  
634      // key = string resource name, value = set of locales in which that name is defined
635      std::map<String16, std::map<String8, SourcePos>> mLocalizations;
636      // set of string resources names that have a default localization
637      std::set<String16> mHasDefaultLocalization;
638      std::queue<CompileResourceWorkItem> mWorkQueue;
639  };
640  
641  #endif
642