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