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