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