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