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