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