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