blob: 865efd1eff8b6228ecb26eed7c2117dfef17a0eb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001//
2// Copyright 2006 The Android Open Source Project
3//
4// Information about assets being operated on.
5//
6#ifndef __AAPT_ASSETS_H
7#define __AAPT_ASSETS_H
8
9#include <stdlib.h>
10#include <utils/AssetManager.h>
11#include <utils/KeyedVector.h>
12#include <utils/String8.h>
13#include <utils/ResourceTypes.h>
14#include <utils/SortedVector.h>
15#include <utils/String8.h>
16#include <utils/Vector.h>
17#include <utils/RefBase.h>
Mathias Agopian55e3d602009-06-05 14:56:35 -070018#include "ZipFile.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019
20#include "Bundle.h"
21#include "SourcePos.h"
22
23using namespace android;
24
25bool valid_symbol_name(const String8& str);
26
27enum {
28 AXIS_NONE = 0,
29 AXIS_MCC = 1,
30 AXIS_MNC,
31 AXIS_LANGUAGE,
32 AXIS_REGION,
Dianne Hackbornc4db95c2009-07-21 17:46:02 -070033 AXIS_SCREENLAYOUTSIZE,
34 AXIS_SCREENLAYOUTLONG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035 AXIS_ORIENTATION,
36 AXIS_DENSITY,
37 AXIS_TOUCHSCREEN,
38 AXIS_KEYSHIDDEN,
39 AXIS_KEYBOARD,
40 AXIS_NAVIGATION,
41 AXIS_SCREENSIZE,
42 AXIS_VERSION
43};
44
45/**
46 * This structure contains a specific variation of a single file out
47 * of all the variations it can have that we can have.
48 */
49struct AaptGroupEntry
50{
51public:
52 AaptGroupEntry() { }
53 AaptGroupEntry(const String8& _locale, const String8& _vendor)
54 : locale(_locale), vendor(_vendor) { }
55
56 String8 mcc;
57 String8 mnc;
58 String8 locale;
59 String8 vendor;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -070060 String8 screenLayoutSize;
61 String8 screenLayoutLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 String8 orientation;
63 String8 density;
64 String8 touchscreen;
65 String8 keysHidden;
66 String8 keyboard;
67 String8 navigation;
68 String8 screenSize;
69 String8 version;
70
71 bool initFromDirName(const char* dir, String8* resType);
72
73 static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
74
75 static bool getMccName(const char* name, ResTable_config* out = NULL);
76 static bool getMncName(const char* name, ResTable_config* out = NULL);
77 static bool getLocaleName(const char* name, ResTable_config* out = NULL);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -070078 static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
79 static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 static bool getOrientationName(const char* name, ResTable_config* out = NULL);
81 static bool getDensityName(const char* name, ResTable_config* out = NULL);
82 static bool getTouchscreenName(const char* name, ResTable_config* out = NULL);
83 static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
84 static bool getKeyboardName(const char* name, ResTable_config* out = NULL);
85 static bool getNavigationName(const char* name, ResTable_config* out = NULL);
86 static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
87 static bool getVersionName(const char* name, ResTable_config* out = NULL);
88
89 int compare(const AaptGroupEntry& o) const;
90
91 ResTable_config toParams() const;
92
93 inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
94 inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
95 inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
96 inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
97 inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
98 inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
99
100 String8 toString() const;
101 String8 toDirName(const String8& resType) const;
102};
103
104inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
105{
106 return lhs.compare(rhs);
107}
108
109inline int strictly_order_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
110{
111 return compare_type(lhs, rhs) < 0;
112}
113
114class AaptGroup;
115
116/**
117 * A single asset file we know about.
118 */
119class AaptFile : public RefBase
120{
121public:
122 AaptFile(const String8& sourceFile, const AaptGroupEntry& groupEntry,
123 const String8& resType)
124 : mGroupEntry(groupEntry)
125 , mResourceType(resType)
126 , mSourceFile(sourceFile)
127 , mData(NULL)
128 , mDataSize(0)
129 , mBufferSize(0)
130 , mCompression(ZipEntry::kCompressStored)
131 {
132 //printf("new AaptFile created %s\n", (const char*)sourceFile);
133 }
Marco Nelissen6a1fade2009-04-20 16:16:01 -0700134 virtual ~AaptFile() {
135 free(mData);
136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137
138 const String8& getPath() const { return mPath; }
139 const AaptGroupEntry& getGroupEntry() const { return mGroupEntry; }
140
141 // Data API. If there is data attached to the file,
142 // getSourceFile() is not used.
143 bool hasData() const { return mData != NULL; }
144 const void* getData() const { return mData; }
145 size_t getSize() const { return mDataSize; }
146 void* editData(size_t size);
147 void* editData(size_t* outSize = NULL);
148 void* padData(size_t wordSize);
149 status_t writeData(const void* data, size_t size);
150 void clearData();
151
152 const String8& getResourceType() const { return mResourceType; }
153
154 // File API. If the file does not hold raw data, this is
155 // a full path to a file on the filesystem that holds its data.
156 const String8& getSourceFile() const { return mSourceFile; }
157
158 String8 getPrintableSource() const;
159
160 // Desired compression method, as per utils/ZipEntry.h. For example,
161 // no compression is ZipEntry::kCompressStored.
162 int getCompressionMethod() const { return mCompression; }
163 void setCompressionMethod(int c) { mCompression = c; }
164private:
165 friend class AaptGroup;
166
167 String8 mPath;
168 AaptGroupEntry mGroupEntry;
169 String8 mResourceType;
170 String8 mSourceFile;
171 void* mData;
172 size_t mDataSize;
173 size_t mBufferSize;
174 int mCompression;
175};
176
177/**
178 * A group of related files (the same file, with different
179 * vendor/locale variations).
180 */
181class AaptGroup : public RefBase
182{
183public:
184 AaptGroup(const String8& leaf, const String8& path)
185 : mLeaf(leaf), mPath(path) { }
186 virtual ~AaptGroup() { }
187
188 const String8& getLeaf() const { return mLeaf; }
189
190 // Returns the relative path after the AaptGroupEntry dirs.
191 const String8& getPath() const { return mPath; }
192
193 const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& getFiles() const
194 { return mFiles; }
195
196 status_t addFile(const sp<AaptFile>& file);
197 void removeFile(size_t index);
198
199 void print() const;
200
201 String8 getPrintableSource() const;
202
203private:
204 String8 mLeaf;
205 String8 mPath;
206
207 DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > mFiles;
208};
209
210/**
211 * A single directory of assets, which can contain for files and other
212 * sub-directories.
213 */
214class AaptDir : public RefBase
215{
216public:
217 AaptDir(const String8& leaf, const String8& path)
218 : mLeaf(leaf), mPath(path) { }
219 virtual ~AaptDir() { }
220
221 const String8& getLeaf() const { return mLeaf; }
222
223 const String8& getPath() const { return mPath; }
224
225 const DefaultKeyedVector<String8, sp<AaptGroup> >& getFiles() const { return mFiles; }
226 const DefaultKeyedVector<String8, sp<AaptDir> >& getDirs() const { return mDirs; }
227
228 status_t addFile(const String8& name, const sp<AaptGroup>& file);
229 status_t addDir(const String8& name, const sp<AaptDir>& dir);
230
231 sp<AaptDir> makeDir(const String8& name);
232
233 void removeFile(const String8& name);
234 void removeDir(const String8& name);
235
236 status_t renameFile(const sp<AaptFile>& file, const String8& newName);
237
238 status_t addLeafFile(const String8& leafName,
239 const sp<AaptFile>& file);
240
241 virtual ssize_t slurpFullTree(Bundle* bundle,
242 const String8& srcDir,
243 const AaptGroupEntry& kind,
244 const String8& resType);
245
246 /*
247 * Perform some sanity checks on the names of files and directories here.
248 * In particular:
249 * - Check for illegal chars in filenames.
250 * - Check filename length.
251 * - Check for presence of ".gz" and non-".gz" copies of same file.
252 * - Check for multiple files whose names match in a case-insensitive
253 * fashion (problematic for some systems).
254 *
255 * Comparing names against all other names is O(n^2). We could speed
256 * it up some by sorting the entries and being smarter about what we
257 * compare against, but I'm not expecting to have enough files in a
258 * single directory to make a noticeable difference in speed.
259 *
260 * Note that sorting here is not enough to guarantee that the package
261 * contents are sorted -- subsequent updates can rearrange things.
262 */
263 status_t validate() const;
264
265 void print() const;
266
267 String8 getPrintableSource() const;
268
269private:
270 String8 mLeaf;
271 String8 mPath;
272
273 DefaultKeyedVector<String8, sp<AaptGroup> > mFiles;
274 DefaultKeyedVector<String8, sp<AaptDir> > mDirs;
275};
276
277/**
278 * All information we know about a particular symbol.
279 */
280class AaptSymbolEntry
281{
282public:
283 AaptSymbolEntry()
284 : isPublic(false), typeCode(TYPE_UNKNOWN)
285 {
286 }
287 AaptSymbolEntry(const String8& _name)
288 : name(_name), isPublic(false), typeCode(TYPE_UNKNOWN)
289 {
290 }
291 AaptSymbolEntry(const AaptSymbolEntry& o)
292 : name(o.name), sourcePos(o.sourcePos), isPublic(o.isPublic)
293 , comment(o.comment), typeComment(o.typeComment)
294 , typeCode(o.typeCode), int32Val(o.int32Val), stringVal(o.stringVal)
295 {
296 }
297 AaptSymbolEntry operator=(const AaptSymbolEntry& o)
298 {
299 sourcePos = o.sourcePos;
300 isPublic = o.isPublic;
301 comment = o.comment;
302 typeComment = o.typeComment;
303 typeCode = o.typeCode;
304 int32Val = o.int32Val;
305 stringVal = o.stringVal;
306 return *this;
307 }
308
309 const String8 name;
310
311 SourcePos sourcePos;
312 bool isPublic;
313
314 String16 comment;
315 String16 typeComment;
316
317 enum {
318 TYPE_UNKNOWN = 0,
319 TYPE_INT32,
320 TYPE_STRING
321 };
322
323 int typeCode;
324
325 // Value. May be one of these.
326 int32_t int32Val;
327 String8 stringVal;
328};
329
330/**
331 * A group of related symbols (such as indices into a string block)
332 * that have been generated from the assets.
333 */
334class AaptSymbols : public RefBase
335{
336public:
337 AaptSymbols() { }
338 virtual ~AaptSymbols() { }
339
340 status_t addSymbol(const String8& name, int32_t value, const SourcePos& pos) {
341 if (!check_valid_symbol_name(name, pos, "symbol")) {
342 return BAD_VALUE;
343 }
344 AaptSymbolEntry& sym = edit_symbol(name, &pos);
345 sym.typeCode = AaptSymbolEntry::TYPE_INT32;
346 sym.int32Val = value;
347 return NO_ERROR;
348 }
349
350 status_t addStringSymbol(const String8& name, const String8& value,
351 const SourcePos& pos) {
352 if (!check_valid_symbol_name(name, pos, "symbol")) {
353 return BAD_VALUE;
354 }
355 AaptSymbolEntry& sym = edit_symbol(name, &pos);
356 sym.typeCode = AaptSymbolEntry::TYPE_STRING;
357 sym.stringVal = value;
358 return NO_ERROR;
359 }
360
361 status_t makeSymbolPublic(const String8& name, const SourcePos& pos) {
362 if (!check_valid_symbol_name(name, pos, "symbol")) {
363 return BAD_VALUE;
364 }
365 AaptSymbolEntry& sym = edit_symbol(name, &pos);
366 sym.isPublic = true;
367 return NO_ERROR;
368 }
369
370 void appendComment(const String8& name, const String16& comment, const SourcePos& pos) {
371 if (comment.size() <= 0) {
372 return;
373 }
374 AaptSymbolEntry& sym = edit_symbol(name, &pos);
375 if (sym.comment.size() == 0) {
376 sym.comment = comment;
377 } else {
378 sym.comment.append(String16("\n"));
379 sym.comment.append(comment);
380 }
381 }
382
383 void appendTypeComment(const String8& name, const String16& comment) {
384 if (comment.size() <= 0) {
385 return;
386 }
387 AaptSymbolEntry& sym = edit_symbol(name, NULL);
388 if (sym.typeComment.size() == 0) {
389 sym.typeComment = comment;
390 } else {
391 sym.typeComment.append(String16("\n"));
392 sym.typeComment.append(comment);
393 }
394 }
395
396 sp<AaptSymbols> addNestedSymbol(const String8& name, const SourcePos& pos) {
397 if (!check_valid_symbol_name(name, pos, "nested symbol")) {
398 return NULL;
399 }
400
401 sp<AaptSymbols> sym = mNestedSymbols.valueFor(name);
402 if (sym == NULL) {
403 sym = new AaptSymbols();
404 mNestedSymbols.add(name, sym);
405 }
406
407 return sym;
408 }
409
410 const KeyedVector<String8, AaptSymbolEntry>& getSymbols() const
411 { return mSymbols; }
412 const DefaultKeyedVector<String8, sp<AaptSymbols> >& getNestedSymbols() const
413 { return mNestedSymbols; }
414
415 const String16& getComment(const String8& name) const
416 { return get_symbol(name).comment; }
417 const String16& getTypeComment(const String8& name) const
418 { return get_symbol(name).typeComment; }
419
420private:
421 bool check_valid_symbol_name(const String8& symbol, const SourcePos& pos, const char* label) {
422 if (valid_symbol_name(symbol)) {
423 return true;
424 }
425 pos.error("invalid %s: '%s'\n", label, symbol.string());
426 return false;
427 }
428 AaptSymbolEntry& edit_symbol(const String8& symbol, const SourcePos* pos) {
429 ssize_t i = mSymbols.indexOfKey(symbol);
430 if (i < 0) {
431 i = mSymbols.add(symbol, AaptSymbolEntry(symbol));
432 }
433 AaptSymbolEntry& sym = mSymbols.editValueAt(i);
434 if (pos != NULL && sym.sourcePos.line < 0) {
435 sym.sourcePos = *pos;
436 }
437 return sym;
438 }
439 const AaptSymbolEntry& get_symbol(const String8& symbol) const {
440 ssize_t i = mSymbols.indexOfKey(symbol);
441 if (i >= 0) {
442 return mSymbols.valueAt(i);
443 }
444 return mDefSymbol;
445 }
446
447 KeyedVector<String8, AaptSymbolEntry> mSymbols;
448 DefaultKeyedVector<String8, sp<AaptSymbols> > mNestedSymbols;
449 AaptSymbolEntry mDefSymbol;
450};
451
Marco Nelissen6a1fade2009-04-20 16:16:01 -0700452class ResourceTypeSet : public RefBase,
453 public KeyedVector<String8,sp<AaptGroup> >
454{
455public:
456 ResourceTypeSet();
457};
458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459
460/**
461 * Asset hierarchy being operated on.
462 */
463class AaptAssets : public AaptDir
464{
465public:
Marco Nelissen6a1fade2009-04-20 16:16:01 -0700466 AaptAssets() : AaptDir(String8(), String8()), mHaveIncludedAssets(false), mRes(NULL) { }
467 virtual ~AaptAssets() { delete mRes; }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468
469 const String8& getPackage() const { return mPackage; }
470 void setPackage(const String8& package) { mPackage = package; mSymbolsPrivatePackage = package; }
471
472 const SortedVector<AaptGroupEntry>& getGroupEntries() const { return mGroupEntries; }
473
474 sp<AaptFile> addFile(const String8& filePath,
475 const AaptGroupEntry& entry,
476 const String8& srcDir,
477 sp<AaptGroup>* outGroup,
478 const String8& resType);
479
480 void addResource(const String8& leafName,
481 const String8& path,
482 const sp<AaptFile>& file,
483 const String8& resType);
484
Dianne Hackborn64551b22009-08-15 00:00:33 -0700485 void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); }
486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 ssize_t slurpFromArgs(Bundle* bundle);
488
489 virtual ssize_t slurpFullTree(Bundle* bundle,
490 const String8& srcDir,
491 const AaptGroupEntry& kind,
492 const String8& resType);
493
494 ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
495 ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
496
497 sp<AaptSymbols> getSymbolsFor(const String8& name);
498
499 const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; }
500
501 String8 getSymbolsPrivatePackage() const { return mSymbolsPrivatePackage; }
502 void setSymbolsPrivatePackage(const String8& pkg) { mSymbolsPrivatePackage = pkg; }
503
504 status_t buildIncludedResources(Bundle* bundle);
505 status_t addIncludedResources(const sp<AaptFile>& file);
506 const ResTable& getIncludedResources() const;
507
508 void print() const;
509
510 inline const Vector<sp<AaptDir> >& resDirs() { return mDirs; }
Joe Onorato1553c822009-08-30 13:36:22 -0700511 sp<AaptDir> resDir(const String8& name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512
513 inline sp<AaptAssets> getOverlay() { return mOverlay; }
514 inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; }
515
516 inline KeyedVector<String8, sp<ResourceTypeSet> >* getResources() { return mRes; }
517 inline void
Marco Nelissen6a1fade2009-04-20 16:16:01 -0700518 setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519
520private:
521 String8 mPackage;
522 SortedVector<AaptGroupEntry> mGroupEntries;
523 DefaultKeyedVector<String8, sp<AaptSymbols> > mSymbols;
524 String8 mSymbolsPrivatePackage;
525
526 Vector<sp<AaptDir> > mDirs;
527
528 bool mHaveIncludedAssets;
529 AssetManager mIncludedAssets;
530
531 sp<AaptAssets> mOverlay;
532 KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
533};
534
535#endif // __AAPT_ASSETS_H
536