]>
git.saurik.com Git - android/aapt.git/blob - AaptAssets.cpp
2 // Copyright 2006 The Android Open Source Project
5 #include "AaptAssets.h"
8 #include <utils/misc.h>
9 #include <utils/SortedVector.h>
15 static const char* kDefaultLocale
= "default";
16 static const char* kWildcardName
= "any";
17 static const char* kAssetDir
= "assets";
18 static const char* kResourceDir
= "res";
19 static const char* kInvalidChars
= "/\\:";
20 static const size_t kMaxAssetFileName
= 100;
22 static const String8
kResString(kResourceDir
);
25 * Names of asset files must meet the following criteria:
27 * - the filename length must be less than kMaxAssetFileName bytes long
28 * (and can't be empty)
29 * - all characters must be 7-bit printable ASCII
30 * - none of { '/' '\\' ':' }
32 * Pass in just the filename, not the full path.
34 static bool validateFileName(const char* fileName
)
36 const char* cp
= fileName
;
40 if ((*cp
& 0x80) != 0)
41 return false; // reject high ASCII
42 if (*cp
< 0x20 || *cp
>= 0x7f)
43 return false; // reject control chars and 0x7f
44 if (strchr(kInvalidChars
, *cp
) != NULL
)
45 return false; // reject path sep chars
50 if (len
< 1 || len
> kMaxAssetFileName
)
51 return false; // reject empty or too long
56 static bool isHidden(const char *root
, const char *path
)
58 const char *ext
= NULL
;
59 const char *type
= NULL
;
61 // Skip all hidden files.
63 // Skip ., .. and .svn but don't chatter about it.
64 if (strcmp(path
, ".") == 0
65 || strcmp(path
, "..") == 0
66 || strcmp(path
, ".svn") == 0) {
70 } else if (path
[0] == '_') {
71 // skip directories starting with _ (don't chatter about it)
72 String8
subdirName(root
);
73 subdirName
.appendPath(path
);
74 if (getFileType(subdirName
.string()) == kFileTypeDirectory
) {
77 } else if (strcmp(path
, "CVS") == 0) {
78 // Skip CVS but don't chatter about it.
80 } else if (strcasecmp(path
, "thumbs.db") == 0
81 || strcasecmp(path
, "picasa.ini") == 0) {
82 // Skip suspected image indexes files.
84 } else if (path
[strlen(path
)-1] == '~') {
85 // Skip suspected emacs backup files.
87 } else if ((ext
= strrchr(path
, '.')) != NULL
&& strcmp(ext
, ".scc") == 0) {
88 // Skip VisualSourceSafe files and don't chatter about it
91 // Let everything else through.
95 /* If we get this far, "type" should be set and the file
98 String8
subdirName(root
);
99 subdirName
.appendPath(path
);
100 fprintf(stderr
, " (skipping %s %s '%s')\n", type
,
101 getFileType(subdirName
.string())==kFileTypeDirectory
? "dir":"file",
102 subdirName
.string());
107 // =========================================================================
108 // =========================================================================
109 // =========================================================================
112 AaptGroupEntry::parseNamePart(const String8
& part
, int* axis
, uint32_t* value
)
114 ResTable_config config
;
117 if (getMccName(part
.string(), &config
)) {
124 if (getMncName(part
.string(), &config
)) {
131 if (part
.length() == 2 && isalpha(part
[0]) && isalpha(part
[1])) {
132 *axis
= AXIS_LANGUAGE
;
133 *value
= part
[1] << 8 | part
[0];
137 // locale - language_REGION
138 if (part
.length() == 5 && isalpha(part
[0]) && isalpha(part
[1])
139 && part
[2] == '_' && isalpha(part
[3]) && isalpha(part
[4])) {
140 *axis
= AXIS_LANGUAGE
;
141 *value
= (part
[4] << 24) | (part
[3] << 16) | (part
[1] << 8) | (part
[0]);
145 // screen layout size
146 if (getScreenLayoutSizeName(part
.string(), &config
)) {
147 *axis
= AXIS_SCREENLAYOUTSIZE
;
148 *value
= (config
.screenLayout
&ResTable_config::MASK_SCREENSIZE
);
152 // screen layout long
153 if (getScreenLayoutLongName(part
.string(), &config
)) {
154 *axis
= AXIS_SCREENLAYOUTLONG
;
155 *value
= (config
.screenLayout
&ResTable_config::MASK_SCREENLONG
);
160 if (getScreenWidthDpName(part
.string(), &config
)) {
161 *axis
= AXIS_SCREENWIDTHDP
;
162 *value
= config
.screenWidthDp
;
167 if (getScreenHeightDpName(part
.string(), &config
)) {
168 *axis
= AXIS_SCREENHEIGHTDP
;
169 *value
= config
.screenHeightDp
;
174 if (getOrientationName(part
.string(), &config
)) {
175 *axis
= AXIS_ORIENTATION
;
176 *value
= config
.orientation
;
181 if (getUiModeTypeName(part
.string(), &config
)) {
182 *axis
= AXIS_UIMODETYPE
;
183 *value
= (config
.uiMode
&ResTable_config::MASK_UI_MODE_TYPE
);
188 if (getUiModeNightName(part
.string(), &config
)) {
189 *axis
= AXIS_UIMODENIGHT
;
190 *value
= (config
.uiMode
&ResTable_config::MASK_UI_MODE_NIGHT
);
195 if (getDensityName(part
.string(), &config
)) {
196 *axis
= AXIS_DENSITY
;
197 *value
= config
.density
;
202 if (getTouchscreenName(part
.string(), &config
)) {
203 *axis
= AXIS_TOUCHSCREEN
;
204 *value
= config
.touchscreen
;
209 if (getKeysHiddenName(part
.string(), &config
)) {
210 *axis
= AXIS_KEYSHIDDEN
;
211 *value
= config
.inputFlags
;
216 if (getKeyboardName(part
.string(), &config
)) {
217 *axis
= AXIS_KEYBOARD
;
218 *value
= config
.keyboard
;
223 if (getNavHiddenName(part
.string(), &config
)) {
224 *axis
= AXIS_NAVHIDDEN
;
225 *value
= config
.inputFlags
;
230 if (getNavigationName(part
.string(), &config
)) {
231 *axis
= AXIS_NAVIGATION
;
232 *value
= config
.navigation
;
237 if (getScreenSizeName(part
.string(), &config
)) {
238 *axis
= AXIS_SCREENSIZE
;
239 *value
= config
.screenSize
;
244 if (getVersionName(part
.string(), &config
)) {
245 *axis
= AXIS_VERSION
;
246 *value
= config
.version
;
254 AaptGroupEntry::initFromDirName(const char* dir
, String8
* resType
)
256 Vector
<String8
> parts
;
258 String8 mcc
, mnc
, loc
, layoutsize
, layoutlong
, orient
, den
;
259 String8 touch
, key
, keysHidden
, nav
, navHidden
, size
, vers
;
260 String8 uiModeType
, uiModeNight
, widthdp
, heightdp
;
264 while (NULL
!= (q
= strchr(p
, '-'))) {
268 //printf("part: %s\n", parts[parts.size()-1].string());
274 //printf("part: %s\n", parts[parts.size()-1].string());
276 const int N
= parts
.size();
278 String8 part
= parts
[index
];
281 if (!isValidResourceType(part
)) {
293 if (getMccName(part
.string())) {
302 //printf("not mcc: %s\n", part.string());
306 if (getMncName(part
.string())) {
315 //printf("not mcc: %s\n", part.string());
319 if (part
.length() == 2 && isalpha(part
[0]) && isalpha(part
[1])) {
328 //printf("not language: %s\n", part.string());
333 && part
.length() == 3 && part
[0] == 'r' && part
[0] && part
[1]) {
336 loc
+= part
.string() + 1;
344 //printf("not region: %s\n", part.string());
347 if (getScreenLayoutSizeName(part
.string())) {
356 //printf("not screen layout size: %s\n", part.string());
359 if (getScreenLayoutLongName(part
.string())) {
368 //printf("not screen layout long: %s\n", part.string());
371 if (getScreenWidthDpName(part
.string())) {
380 //printf("not screen width dp: %s\n", part.string());
383 if (getScreenHeightDpName(part
.string())) {
392 //printf("not screen height dp: %s\n", part.string());
396 if (getOrientationName(part
.string())) {
405 //printf("not orientation: %s\n", part.string());
409 if (getUiModeTypeName(part
.string())) {
418 //printf("not ui mode type: %s\n", part.string());
422 if (getUiModeNightName(part
.string())) {
431 //printf("not ui mode night: %s\n", part.string());
435 if (getDensityName(part
.string())) {
444 //printf("not density: %s\n", part.string());
448 if (getTouchscreenName(part
.string())) {
457 //printf("not touchscreen: %s\n", part.string());
461 if (getKeysHiddenName(part
.string())) {
470 //printf("not keysHidden: %s\n", part.string());
474 if (getKeyboardName(part
.string())) {
483 //printf("not keyboard: %s\n", part.string());
487 if (getNavHiddenName(part
.string())) {
496 //printf("not navHidden: %s\n", part.string());
499 if (getNavigationName(part
.string())) {
508 //printf("not navigation: %s\n", part.string());
511 if (getScreenSizeName(part
.string())) {
520 //printf("not screen size: %s\n", part.string());
523 if (getVersionName(part
.string())) {
532 //printf("not version: %s\n", part.string());
535 // if there are extra parts, it doesn't match
542 this->screenLayoutSize
= layoutsize
;
543 this->screenLayoutLong
= layoutlong
;
544 this->screenWidthDp
= widthdp
;
545 this->screenHeightDp
= heightdp
;
546 this->orientation
= orient
;
547 this->uiModeType
= uiModeType
;
548 this->uiModeNight
= uiModeNight
;
550 this->touchscreen
= touch
;
551 this->keysHidden
= keysHidden
;
552 this->keyboard
= key
;
553 this->navHidden
= navHidden
;
554 this->navigation
= nav
;
555 this->screenSize
= size
;
556 this->version
= vers
;
558 // what is this anyway?
565 AaptGroupEntry::toString() const
567 String8 s
= this->mcc
;
573 s
+= screenLayoutSize
;
575 s
+= screenLayoutLong
;
581 s
+= this->orientation
;
606 AaptGroupEntry::toDirName(const String8
& resType
) const
609 if (this->mcc
!= "") {
613 if (this->mnc
!= "") {
617 if (this->locale
!= "") {
621 if (this->screenLayoutSize
!= "") {
623 s
+= screenLayoutSize
;
625 if (this->screenLayoutLong
!= "") {
627 s
+= screenLayoutLong
;
629 if (this->screenWidthDp
!= "") {
633 if (this->screenHeightDp
!= "") {
637 if (this->orientation
!= "") {
641 if (this->uiModeType
!= "") {
645 if (this->uiModeNight
!= "") {
649 if (this->density
!= "") {
653 if (this->touchscreen
!= "") {
657 if (this->keysHidden
!= "") {
661 if (this->keyboard
!= "") {
665 if (this->navHidden
!= "") {
669 if (this->navigation
!= "") {
673 if (this->screenSize
!= "") {
677 if (this->version
!= "") {
685 bool AaptGroupEntry::getMccName(const char* name
,
686 ResTable_config
* out
)
688 if (strcmp(name
, kWildcardName
) == 0) {
689 if (out
) out
->mcc
= 0;
692 const char* c
= name
;
693 if (tolower(*c
) != 'm') return false;
695 if (tolower(*c
) != 'c') return false;
697 if (tolower(*c
) != 'c') return false;
702 while (*c
>= '0' && *c
<= '9') {
705 if (*c
!= 0) return false;
706 if (c
-val
!= 3) return false;
710 if (out
) out
->mcc
= d
;
717 bool AaptGroupEntry::getMncName(const char* name
,
718 ResTable_config
* out
)
720 if (strcmp(name
, kWildcardName
) == 0) {
721 if (out
) out
->mcc
= 0;
724 const char* c
= name
;
725 if (tolower(*c
) != 'm') return false;
727 if (tolower(*c
) != 'n') return false;
729 if (tolower(*c
) != 'c') return false;
734 while (*c
>= '0' && *c
<= '9') {
737 if (*c
!= 0) return false;
738 if (c
-val
== 0 || c
-val
> 3) return false;
741 out
->mnc
= atoi(val
);
748 * Does this directory name fit the pattern of a locale dir ("en-rUS" or
751 * TODO: Should insist that the first two letters are lower case, and the
752 * second two are upper.
754 bool AaptGroupEntry::getLocaleName(const char* fileName
,
755 ResTable_config
* out
)
757 if (strcmp(fileName
, kWildcardName
) == 0
758 || strcmp(fileName
, kDefaultLocale
) == 0) {
760 out
->language
[0] = 0;
761 out
->language
[1] = 0;
768 if (strlen(fileName
) == 2 && isalpha(fileName
[0]) && isalpha(fileName
[1])) {
770 out
->language
[0] = fileName
[0];
771 out
->language
[1] = fileName
[1];
778 if (strlen(fileName
) == 5 &&
779 isalpha(fileName
[0]) &&
780 isalpha(fileName
[1]) &&
781 fileName
[2] == '-' &&
782 isalpha(fileName
[3]) &&
783 isalpha(fileName
[4])) {
785 out
->language
[0] = fileName
[0];
786 out
->language
[1] = fileName
[1];
787 out
->country
[0] = fileName
[3];
788 out
->country
[1] = fileName
[4];
796 bool AaptGroupEntry::getScreenLayoutSizeName(const char* name
,
797 ResTable_config
* out
)
799 if (strcmp(name
, kWildcardName
) == 0) {
800 if (out
) out
->screenLayout
=
801 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
802 | ResTable_config::SCREENSIZE_ANY
;
804 } else if (strcmp(name
, "small") == 0) {
805 if (out
) out
->screenLayout
=
806 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
807 | ResTable_config::SCREENSIZE_SMALL
;
809 } else if (strcmp(name
, "normal") == 0) {
810 if (out
) out
->screenLayout
=
811 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
812 | ResTable_config::SCREENSIZE_NORMAL
;
814 } else if (strcmp(name
, "large") == 0) {
815 if (out
) out
->screenLayout
=
816 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
817 | ResTable_config::SCREENSIZE_LARGE
;
819 } else if (strcmp(name
, "xlarge") == 0) {
820 if (out
) out
->screenLayout
=
821 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
822 | ResTable_config::SCREENSIZE_XLARGE
;
829 bool AaptGroupEntry::getScreenLayoutLongName(const char* name
,
830 ResTable_config
* out
)
832 if (strcmp(name
, kWildcardName
) == 0) {
833 if (out
) out
->screenLayout
=
834 (out
->screenLayout
&~ResTable_config::MASK_SCREENLONG
)
835 | ResTable_config::SCREENLONG_ANY
;
837 } else if (strcmp(name
, "long") == 0) {
838 if (out
) out
->screenLayout
=
839 (out
->screenLayout
&~ResTable_config::MASK_SCREENLONG
)
840 | ResTable_config::SCREENLONG_YES
;
842 } else if (strcmp(name
, "notlong") == 0) {
843 if (out
) out
->screenLayout
=
844 (out
->screenLayout
&~ResTable_config::MASK_SCREENLONG
)
845 | ResTable_config::SCREENLONG_NO
;
852 bool AaptGroupEntry::getOrientationName(const char* name
,
853 ResTable_config
* out
)
855 if (strcmp(name
, kWildcardName
) == 0) {
856 if (out
) out
->orientation
= out
->ORIENTATION_ANY
;
858 } else if (strcmp(name
, "port") == 0) {
859 if (out
) out
->orientation
= out
->ORIENTATION_PORT
;
861 } else if (strcmp(name
, "land") == 0) {
862 if (out
) out
->orientation
= out
->ORIENTATION_LAND
;
864 } else if (strcmp(name
, "square") == 0) {
865 if (out
) out
->orientation
= out
->ORIENTATION_SQUARE
;
872 bool AaptGroupEntry::getUiModeTypeName(const char* name
,
873 ResTable_config
* out
)
875 if (strcmp(name
, kWildcardName
) == 0) {
876 if (out
) out
->uiMode
=
877 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_TYPE
)
878 | ResTable_config::UI_MODE_TYPE_ANY
;
880 } else if (strcmp(name
, "desk") == 0) {
881 if (out
) out
->uiMode
=
882 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_TYPE
)
883 | ResTable_config::UI_MODE_TYPE_DESK
;
885 } else if (strcmp(name
, "car") == 0) {
886 if (out
) out
->uiMode
=
887 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_TYPE
)
888 | ResTable_config::UI_MODE_TYPE_CAR
;
895 bool AaptGroupEntry::getUiModeNightName(const char* name
,
896 ResTable_config
* out
)
898 if (strcmp(name
, kWildcardName
) == 0) {
899 if (out
) out
->uiMode
=
900 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
901 | ResTable_config::UI_MODE_NIGHT_ANY
;
903 } else if (strcmp(name
, "night") == 0) {
904 if (out
) out
->uiMode
=
905 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
906 | ResTable_config::UI_MODE_NIGHT_YES
;
908 } else if (strcmp(name
, "notnight") == 0) {
909 if (out
) out
->uiMode
=
910 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
911 | ResTable_config::UI_MODE_NIGHT_NO
;
918 bool AaptGroupEntry::getDensityName(const char* name
,
919 ResTable_config
* out
)
921 if (strcmp(name
, kWildcardName
) == 0) {
922 if (out
) out
->density
= ResTable_config::DENSITY_DEFAULT
;
926 if (strcmp(name
, "nodpi") == 0) {
927 if (out
) out
->density
= ResTable_config::DENSITY_NONE
;
931 if (strcmp(name
, "ldpi") == 0) {
932 if (out
) out
->density
= ResTable_config::DENSITY_LOW
;
936 if (strcmp(name
, "mdpi") == 0) {
937 if (out
) out
->density
= ResTable_config::DENSITY_MEDIUM
;
941 if (strcmp(name
, "hdpi") == 0) {
942 if (out
) out
->density
= ResTable_config::DENSITY_HIGH
;
946 if (strcmp(name
, "xhdpi") == 0) {
947 if (out
) out
->density
= ResTable_config::DENSITY_MEDIUM
*2;
951 char* c
= (char*)name
;
952 while (*c
>= '0' && *c
<= '9') {
956 // check that we have 'dpi' after the last digit.
957 if (toupper(c
[0]) != 'D' ||
958 toupper(c
[1]) != 'P' ||
959 toupper(c
[2]) != 'I' ||
964 // temporarily replace the first letter with \0 to
973 if (out
) out
->density
= d
;
980 bool AaptGroupEntry::getTouchscreenName(const char* name
,
981 ResTable_config
* out
)
983 if (strcmp(name
, kWildcardName
) == 0) {
984 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_ANY
;
986 } else if (strcmp(name
, "notouch") == 0) {
987 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_NOTOUCH
;
989 } else if (strcmp(name
, "stylus") == 0) {
990 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_STYLUS
;
992 } else if (strcmp(name
, "finger") == 0) {
993 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_FINGER
;
1000 bool AaptGroupEntry::getKeysHiddenName(const char* name
,
1001 ResTable_config
* out
)
1005 if (strcmp(name
, kWildcardName
) == 0) {
1006 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1007 value
= ResTable_config::KEYSHIDDEN_ANY
;
1008 } else if (strcmp(name
, "keysexposed") == 0) {
1009 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1010 value
= ResTable_config::KEYSHIDDEN_NO
;
1011 } else if (strcmp(name
, "keyshidden") == 0) {
1012 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1013 value
= ResTable_config::KEYSHIDDEN_YES
;
1014 } else if (strcmp(name
, "keyssoft") == 0) {
1015 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1016 value
= ResTable_config::KEYSHIDDEN_SOFT
;
1020 if (out
) out
->inputFlags
= (out
->inputFlags
&~mask
) | value
;
1027 bool AaptGroupEntry::getKeyboardName(const char* name
,
1028 ResTable_config
* out
)
1030 if (strcmp(name
, kWildcardName
) == 0) {
1031 if (out
) out
->keyboard
= out
->KEYBOARD_ANY
;
1033 } else if (strcmp(name
, "nokeys") == 0) {
1034 if (out
) out
->keyboard
= out
->KEYBOARD_NOKEYS
;
1036 } else if (strcmp(name
, "qwerty") == 0) {
1037 if (out
) out
->keyboard
= out
->KEYBOARD_QWERTY
;
1039 } else if (strcmp(name
, "12key") == 0) {
1040 if (out
) out
->keyboard
= out
->KEYBOARD_12KEY
;
1047 bool AaptGroupEntry::getNavHiddenName(const char* name
,
1048 ResTable_config
* out
)
1052 if (strcmp(name
, kWildcardName
) == 0) {
1053 mask
= ResTable_config::MASK_NAVHIDDEN
;
1054 value
= ResTable_config::NAVHIDDEN_ANY
;
1055 } else if (strcmp(name
, "navexposed") == 0) {
1056 mask
= ResTable_config::MASK_NAVHIDDEN
;
1057 value
= ResTable_config::NAVHIDDEN_NO
;
1058 } else if (strcmp(name
, "navhidden") == 0) {
1059 mask
= ResTable_config::MASK_NAVHIDDEN
;
1060 value
= ResTable_config::NAVHIDDEN_YES
;
1064 if (out
) out
->inputFlags
= (out
->inputFlags
&~mask
) | value
;
1071 bool AaptGroupEntry::getNavigationName(const char* name
,
1072 ResTable_config
* out
)
1074 if (strcmp(name
, kWildcardName
) == 0) {
1075 if (out
) out
->navigation
= out
->NAVIGATION_ANY
;
1077 } else if (strcmp(name
, "nonav") == 0) {
1078 if (out
) out
->navigation
= out
->NAVIGATION_NONAV
;
1080 } else if (strcmp(name
, "dpad") == 0) {
1081 if (out
) out
->navigation
= out
->NAVIGATION_DPAD
;
1083 } else if (strcmp(name
, "trackball") == 0) {
1084 if (out
) out
->navigation
= out
->NAVIGATION_TRACKBALL
;
1086 } else if (strcmp(name
, "wheel") == 0) {
1087 if (out
) out
->navigation
= out
->NAVIGATION_WHEEL
;
1094 bool AaptGroupEntry::getScreenSizeName(const char* name
, ResTable_config
* out
)
1096 if (strcmp(name
, kWildcardName
) == 0) {
1098 out
->screenWidth
= out
->SCREENWIDTH_ANY
;
1099 out
->screenHeight
= out
->SCREENHEIGHT_ANY
;
1104 const char* x
= name
;
1105 while (*x
>= '0' && *x
<= '9') x
++;
1106 if (x
== name
|| *x
!= 'x') return false;
1107 String8
xName(name
, x
-name
);
1111 while (*y
>= '0' && *y
<= '9') y
++;
1112 if (y
== name
|| *y
!= 0) return false;
1113 String8
yName(x
, y
-x
);
1115 uint16_t w
= (uint16_t)atoi(xName
.string());
1116 uint16_t h
= (uint16_t)atoi(yName
.string());
1122 out
->screenWidth
= w
;
1123 out
->screenHeight
= h
;
1129 bool AaptGroupEntry::getScreenWidthDpName(const char* name
, ResTable_config
* out
)
1131 if (strcmp(name
, kWildcardName
) == 0) {
1133 out
->screenWidthDp
= out
->SCREENWIDTH_ANY
;
1138 if (*name
!= 'w') return false;
1140 const char* x
= name
;
1141 while (*x
>= '0' && *x
<= '9') x
++;
1142 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1143 String8
xName(name
, x
-name
);
1146 out
->screenWidthDp
= (uint16_t)atoi(xName
.string());
1152 bool AaptGroupEntry::getScreenHeightDpName(const char* name
, ResTable_config
* out
)
1154 if (strcmp(name
, kWildcardName
) == 0) {
1156 out
->screenHeightDp
= out
->SCREENWIDTH_ANY
;
1161 if (*name
!= 'h') return false;
1163 const char* x
= name
;
1164 while (*x
>= '0' && *x
<= '9') x
++;
1165 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1166 String8
xName(name
, x
-name
);
1169 out
->screenHeightDp
= (uint16_t)atoi(xName
.string());
1175 bool AaptGroupEntry::getVersionName(const char* name
, ResTable_config
* out
)
1177 if (strcmp(name
, kWildcardName
) == 0) {
1179 out
->sdkVersion
= out
->SDKVERSION_ANY
;
1180 out
->minorVersion
= out
->MINORVERSION_ANY
;
1190 const char* s
= name
;
1191 while (*s
>= '0' && *s
<= '9') s
++;
1192 if (s
== name
|| *s
!= 0) return false;
1193 String8
sdkName(name
, s
-name
);
1196 out
->sdkVersion
= (uint16_t)atoi(sdkName
.string());
1197 out
->minorVersion
= 0;
1203 int AaptGroupEntry::compare(const AaptGroupEntry
& o
) const
1205 int v
= mcc
.compare(o
.mcc
);
1206 if (v
== 0) v
= mnc
.compare(o
.mnc
);
1207 if (v
== 0) v
= locale
.compare(o
.locale
);
1208 if (v
== 0) v
= vendor
.compare(o
.vendor
);
1209 if (v
== 0) v
= screenLayoutSize
.compare(o
.screenLayoutSize
);
1210 if (v
== 0) v
= screenLayoutLong
.compare(o
.screenLayoutLong
);
1211 if (v
== 0) v
= screenWidthDp
.compare(o
.screenWidthDp
);
1212 if (v
== 0) v
= screenHeightDp
.compare(o
.screenHeightDp
);
1213 if (v
== 0) v
= orientation
.compare(o
.orientation
);
1214 if (v
== 0) v
= uiModeType
.compare(o
.uiModeType
);
1215 if (v
== 0) v
= uiModeNight
.compare(o
.uiModeNight
);
1216 if (v
== 0) v
= density
.compare(o
.density
);
1217 if (v
== 0) v
= touchscreen
.compare(o
.touchscreen
);
1218 if (v
== 0) v
= keysHidden
.compare(o
.keysHidden
);
1219 if (v
== 0) v
= keyboard
.compare(o
.keyboard
);
1220 if (v
== 0) v
= navHidden
.compare(o
.navHidden
);
1221 if (v
== 0) v
= navigation
.compare(o
.navigation
);
1222 if (v
== 0) v
= screenSize
.compare(o
.screenSize
);
1223 if (v
== 0) v
= version
.compare(o
.version
);
1227 ResTable_config
AaptGroupEntry::toParams() const
1229 ResTable_config params
;
1230 memset(¶ms
, 0, sizeof(params
));
1231 getMccName(mcc
.string(), ¶ms
);
1232 getMncName(mnc
.string(), ¶ms
);
1233 getLocaleName(locale
.string(), ¶ms
);
1234 getScreenLayoutSizeName(screenLayoutSize
.string(), ¶ms
);
1235 getScreenLayoutLongName(screenLayoutLong
.string(), ¶ms
);
1236 getScreenWidthDpName(screenWidthDp
.string(), ¶ms
);
1237 getScreenHeightDpName(screenHeightDp
.string(), ¶ms
);
1238 getOrientationName(orientation
.string(), ¶ms
);
1239 getUiModeTypeName(uiModeType
.string(), ¶ms
);
1240 getUiModeNightName(uiModeNight
.string(), ¶ms
);
1241 getDensityName(density
.string(), ¶ms
);
1242 getTouchscreenName(touchscreen
.string(), ¶ms
);
1243 getKeysHiddenName(keysHidden
.string(), ¶ms
);
1244 getKeyboardName(keyboard
.string(), ¶ms
);
1245 getNavHiddenName(navHidden
.string(), ¶ms
);
1246 getNavigationName(navigation
.string(), ¶ms
);
1247 getScreenSizeName(screenSize
.string(), ¶ms
);
1248 getVersionName(version
.string(), ¶ms
);
1250 // Fix up version number based on specified parameters.
1252 if (params
.screenWidthDp
!= ResTable_config::SCREENWIDTH_ANY
1253 || params
.screenHeightDp
!= ResTable_config::SCREENHEIGHT_ANY
) {
1255 } else if ((params
.uiMode
&ResTable_config::MASK_UI_MODE_TYPE
)
1256 != ResTable_config::UI_MODE_TYPE_ANY
1257 || (params
.uiMode
&ResTable_config::MASK_UI_MODE_NIGHT
)
1258 != ResTable_config::UI_MODE_NIGHT_ANY
) {
1260 } else if ((params
.screenLayout
&ResTable_config::MASK_SCREENSIZE
)
1261 != ResTable_config::SCREENSIZE_ANY
1262 || (params
.screenLayout
&ResTable_config::MASK_SCREENLONG
)
1263 != ResTable_config::SCREENLONG_ANY
1264 || params
.density
!= ResTable_config::DENSITY_DEFAULT
) {
1268 if (minSdk
> params
.sdkVersion
) {
1269 params
.sdkVersion
= minSdk
;
1275 // =========================================================================
1276 // =========================================================================
1277 // =========================================================================
1279 void* AaptFile::editData(size_t size
)
1281 if (size
<= mBufferSize
) {
1285 size_t allocSize
= (size
*3)/2;
1286 void* buf
= realloc(mData
, allocSize
);
1292 mBufferSize
= allocSize
;
1296 void* AaptFile::editData(size_t* outSize
)
1299 *outSize
= mDataSize
;
1304 void* AaptFile::padData(size_t wordSize
)
1306 const size_t extra
= mDataSize%wordSize
;
1311 size_t initial
= mDataSize
;
1312 void* data
= editData(initial
+(wordSize
-extra
));
1314 memset(((uint8_t*)data
) + initial
, 0, wordSize
-extra
);
1319 status_t
AaptFile::writeData(const void* data
, size_t size
)
1321 size_t end
= mDataSize
;
1322 size_t total
= size
+ end
;
1323 void* buf
= editData(total
);
1325 return UNKNOWN_ERROR
;
1327 memcpy(((char*)buf
)+end
, data
, size
);
1331 void AaptFile::clearData()
1333 if (mData
!= NULL
) free(mData
);
1339 String8
AaptFile::getPrintableSource() const
1342 String8
name(mGroupEntry
.locale
.string());
1343 name
.appendPath(mGroupEntry
.vendor
.string());
1344 name
.appendPath(mPath
);
1345 name
.append(" #generated");
1351 // =========================================================================
1352 // =========================================================================
1353 // =========================================================================
1355 status_t
AaptGroup::addFile(const sp
<AaptFile
>& file
)
1357 if (mFiles
.indexOfKey(file
->getGroupEntry()) < 0) {
1358 file
->mPath
= mPath
;
1359 mFiles
.add(file
->getGroupEntry(), file
);
1363 SourcePos(file
->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.",
1364 getPrintableSource().string());
1365 return UNKNOWN_ERROR
;
1368 void AaptGroup::removeFile(size_t index
)
1370 mFiles
.removeItemsAt(index
);
1373 void AaptGroup::print() const
1375 printf(" %s\n", getPath().string());
1376 const size_t N
=mFiles
.size();
1378 for (i
=0; i
<N
; i
++) {
1379 sp
<AaptFile
> file
= mFiles
.valueAt(i
);
1380 const AaptGroupEntry
& e
= file
->getGroupEntry();
1381 if (file
->hasData()) {
1382 printf(" Gen: (%s) %d bytes\n", e
.toString().string(),
1383 (int)file
->getSize());
1385 printf(" Src: %s\n", file
->getPrintableSource().string());
1390 String8
AaptGroup::getPrintableSource() const
1392 if (mFiles
.size() > 0) {
1393 // Arbitrarily pull the first source file out of the list.
1394 return mFiles
.valueAt(0)->getPrintableSource();
1397 // Should never hit this case, but to be safe...
1402 // =========================================================================
1403 // =========================================================================
1404 // =========================================================================
1406 status_t
AaptDir::addFile(const String8
& name
, const sp
<AaptGroup
>& file
)
1408 if (mFiles
.indexOfKey(name
) >= 0) {
1409 return ALREADY_EXISTS
;
1411 mFiles
.add(name
, file
);
1415 status_t
AaptDir::addDir(const String8
& name
, const sp
<AaptDir
>& dir
)
1417 if (mDirs
.indexOfKey(name
) >= 0) {
1418 return ALREADY_EXISTS
;
1420 mDirs
.add(name
, dir
);
1424 sp
<AaptDir
> AaptDir::makeDir(const String8
& path
)
1427 String8 remain
= path
;
1429 sp
<AaptDir
> subdir
= this;
1430 while (name
= remain
.walkPath(&remain
), remain
!= "") {
1431 subdir
= subdir
->makeDir(name
);
1434 ssize_t i
= subdir
->mDirs
.indexOfKey(name
);
1436 return subdir
->mDirs
.valueAt(i
);
1438 sp
<AaptDir
> dir
= new AaptDir(name
, subdir
->mPath
.appendPathCopy(name
));
1439 subdir
->mDirs
.add(name
, dir
);
1443 void AaptDir::removeFile(const String8
& name
)
1445 mFiles
.removeItem(name
);
1448 void AaptDir::removeDir(const String8
& name
)
1450 mDirs
.removeItem(name
);
1453 status_t
AaptDir::renameFile(const sp
<AaptFile
>& file
, const String8
& newName
)
1455 sp
<AaptGroup
> origGroup
;
1457 // Find and remove the given file with shear, brute force!
1458 const size_t NG
= mFiles
.size();
1460 for (i
=0; origGroup
== NULL
&& i
<NG
; i
++) {
1461 sp
<AaptGroup
> g
= mFiles
.valueAt(i
);
1462 const size_t NF
= g
->getFiles().size();
1463 for (size_t j
=0; j
<NF
; j
++) {
1464 if (g
->getFiles().valueAt(j
) == file
) {
1468 mFiles
.removeItemsAt(i
);
1475 //printf("Renaming %s to %s\n", file->getPath().getPathName(), newName.string());
1477 // Place the file under its new name.
1478 if (origGroup
!= NULL
) {
1479 return addLeafFile(newName
, file
);
1485 status_t
AaptDir::addLeafFile(const String8
& leafName
, const sp
<AaptFile
>& file
)
1487 sp
<AaptGroup
> group
;
1488 if (mFiles
.indexOfKey(leafName
) >= 0) {
1489 group
= mFiles
.valueFor(leafName
);
1491 group
= new AaptGroup(leafName
, mPath
.appendPathCopy(leafName
));
1492 mFiles
.add(leafName
, group
);
1495 return group
->addFile(file
);
1498 ssize_t
AaptDir::slurpFullTree(Bundle
* bundle
, const String8
& srcDir
,
1499 const AaptGroupEntry
& kind
, const String8
& resType
)
1501 Vector
<String8
> fileNames
;
1506 dir
= opendir(srcDir
.string());
1508 fprintf(stderr
, "ERROR: opendir(%s): %s\n", srcDir
.string(), strerror(errno
));
1509 return UNKNOWN_ERROR
;
1513 * Slurp the filenames out of the directory.
1516 struct dirent
* entry
;
1518 entry
= readdir(dir
);
1522 if (isHidden(srcDir
.string(), entry
->d_name
))
1525 fileNames
.add(String8(entry
->d_name
));
1534 * Stash away the files and recursively descend into subdirectories.
1536 const size_t N
= fileNames
.size();
1538 for (i
= 0; i
< N
; i
++) {
1539 String8
pathName(srcDir
);
1542 pathName
.appendPath(fileNames
[i
].string());
1543 type
= getFileType(pathName
.string());
1544 if (type
== kFileTypeDirectory
) {
1546 bool notAdded
= false;
1547 if (mDirs
.indexOfKey(fileNames
[i
]) >= 0) {
1548 subdir
= mDirs
.valueFor(fileNames
[i
]);
1550 subdir
= new AaptDir(fileNames
[i
], mPath
.appendPathCopy(fileNames
[i
]));
1553 ssize_t res
= subdir
->slurpFullTree(bundle
, pathName
, kind
,
1555 if (res
< NO_ERROR
) {
1558 if (res
> 0 && notAdded
) {
1559 mDirs
.add(fileNames
[i
], subdir
);
1562 } else if (type
== kFileTypeRegular
) {
1563 sp
<AaptFile
> file
= new AaptFile(pathName
, kind
, resType
);
1564 status_t err
= addLeafFile(fileNames
[i
], file
);
1565 if (err
!= NO_ERROR
) {
1572 if (bundle
->getVerbose())
1573 printf(" (ignoring non-file/dir '%s')\n", pathName
.string());
1580 status_t
AaptDir::validate() const
1582 const size_t NF
= mFiles
.size();
1583 const size_t ND
= mDirs
.size();
1585 for (i
= 0; i
< NF
; i
++) {
1586 if (!validateFileName(mFiles
.valueAt(i
)->getLeaf().string())) {
1587 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1588 "Invalid filename. Unable to add.");
1589 return UNKNOWN_ERROR
;
1593 for (j
= i
+1; j
< NF
; j
++) {
1594 if (strcasecmp(mFiles
.valueAt(i
)->getLeaf().string(),
1595 mFiles
.valueAt(j
)->getLeaf().string()) == 0) {
1596 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1597 "File is case-insensitive equivalent to: %s",
1598 mFiles
.valueAt(j
)->getPrintableSource().string());
1599 return UNKNOWN_ERROR
;
1602 // TODO: if ".gz", check for non-.gz; if non-, check for ".gz"
1603 // (this is mostly caught by the "marked" stuff, below)
1606 for (j
= 0; j
< ND
; j
++) {
1607 if (strcasecmp(mFiles
.valueAt(i
)->getLeaf().string(),
1608 mDirs
.valueAt(j
)->getLeaf().string()) == 0) {
1609 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1610 "File conflicts with dir from: %s",
1611 mDirs
.valueAt(j
)->getPrintableSource().string());
1612 return UNKNOWN_ERROR
;
1617 for (i
= 0; i
< ND
; i
++) {
1618 if (!validateFileName(mDirs
.valueAt(i
)->getLeaf().string())) {
1619 SourcePos(mDirs
.valueAt(i
)->getPrintableSource(), -1).error(
1620 "Invalid directory name, unable to add.");
1621 return UNKNOWN_ERROR
;
1625 for (j
= i
+1; j
< ND
; j
++) {
1626 if (strcasecmp(mDirs
.valueAt(i
)->getLeaf().string(),
1627 mDirs
.valueAt(j
)->getLeaf().string()) == 0) {
1628 SourcePos(mDirs
.valueAt(i
)->getPrintableSource(), -1).error(
1629 "Directory is case-insensitive equivalent to: %s",
1630 mDirs
.valueAt(j
)->getPrintableSource().string());
1631 return UNKNOWN_ERROR
;
1635 status_t err
= mDirs
.valueAt(i
)->validate();
1636 if (err
!= NO_ERROR
) {
1644 void AaptDir::print() const
1646 const size_t ND
=getDirs().size();
1648 for (i
=0; i
<ND
; i
++) {
1649 getDirs().valueAt(i
)->print();
1652 const size_t NF
=getFiles().size();
1653 for (i
=0; i
<NF
; i
++) {
1654 getFiles().valueAt(i
)->print();
1658 String8
AaptDir::getPrintableSource() const
1660 if (mFiles
.size() > 0) {
1661 // Arbitrarily pull the first file out of the list as the source dir.
1662 return mFiles
.valueAt(0)->getPrintableSource().getPathDir();
1664 if (mDirs
.size() > 0) {
1665 // Or arbitrarily pull the first dir out of the list as the source dir.
1666 return mDirs
.valueAt(0)->getPrintableSource().getPathDir();
1669 // Should never hit this case, but to be safe...
1674 // =========================================================================
1675 // =========================================================================
1676 // =========================================================================
1678 sp
<AaptFile
> AaptAssets::addFile(
1679 const String8
& filePath
, const AaptGroupEntry
& entry
,
1680 const String8
& srcDir
, sp
<AaptGroup
>* outGroup
,
1681 const String8
& resType
)
1683 sp
<AaptDir
> dir
= this;
1684 sp
<AaptGroup
> group
;
1686 String8 root
, remain(filePath
), partialPath
;
1687 while (remain
.length() > 0) {
1688 root
= remain
.walkPath(&remain
);
1689 partialPath
.appendPath(root
);
1691 const String8
rootStr(root
);
1693 if (remain
.length() == 0) {
1694 ssize_t i
= dir
->getFiles().indexOfKey(rootStr
);
1696 group
= dir
->getFiles().valueAt(i
);
1698 group
= new AaptGroup(rootStr
, filePath
);
1699 status_t res
= dir
->addFile(rootStr
, group
);
1700 if (res
!= NO_ERROR
) {
1704 file
= new AaptFile(srcDir
.appendPathCopy(filePath
), entry
, resType
);
1705 status_t res
= group
->addFile(file
);
1706 if (res
!= NO_ERROR
) {
1712 ssize_t i
= dir
->getDirs().indexOfKey(rootStr
);
1714 dir
= dir
->getDirs().valueAt(i
);
1716 sp
<AaptDir
> subdir
= new AaptDir(rootStr
, partialPath
);
1717 status_t res
= dir
->addDir(rootStr
, subdir
);
1718 if (res
!= NO_ERROR
) {
1726 mGroupEntries
.add(entry
);
1727 if (outGroup
) *outGroup
= group
;
1731 void AaptAssets::addResource(const String8
& leafName
, const String8
& path
,
1732 const sp
<AaptFile
>& file
, const String8
& resType
)
1734 sp
<AaptDir
> res
= AaptDir::makeDir(kResString
);
1735 String8 dirname
= file
->getGroupEntry().toDirName(resType
);
1736 sp
<AaptDir
> subdir
= res
->makeDir(dirname
);
1737 sp
<AaptGroup
> grr
= new AaptGroup(leafName
, path
);
1740 subdir
->addFile(leafName
, grr
);
1744 ssize_t
AaptAssets::slurpFromArgs(Bundle
* bundle
)
1749 const Vector
<const char *>& resDirs
= bundle
->getResourceSourceDirs();
1750 const size_t dirCount
=resDirs
.size();
1751 sp
<AaptAssets
> current
= this;
1753 const int N
= bundle
->getFileSpecCount();
1756 * If a package manifest was specified, include that first.
1758 if (bundle
->getAndroidManifestFile() != NULL
) {
1759 // place at root of zip.
1760 String8
srcFile(bundle
->getAndroidManifestFile());
1761 addFile(srcFile
.getPathLeaf(), AaptGroupEntry(), srcFile
.getPathDir(),
1767 * If a directory of custom assets was supplied, slurp 'em up.
1769 if (bundle
->getAssetSourceDir()) {
1770 const char* assetDir
= bundle
->getAssetSourceDir();
1772 FileType type
= getFileType(assetDir
);
1773 if (type
== kFileTypeNonexistent
) {
1774 fprintf(stderr
, "ERROR: asset directory '%s' does not exist\n", assetDir
);
1775 return UNKNOWN_ERROR
;
1777 if (type
!= kFileTypeDirectory
) {
1778 fprintf(stderr
, "ERROR: '%s' is not a directory\n", assetDir
);
1779 return UNKNOWN_ERROR
;
1782 String8
assetRoot(assetDir
);
1783 sp
<AaptDir
> assetAaptDir
= makeDir(String8(kAssetDir
));
1784 AaptGroupEntry group
;
1785 count
= assetAaptDir
->slurpFullTree(bundle
, assetRoot
, group
,
1792 mGroupEntries
.add(group
);
1794 totalCount
+= count
;
1796 if (bundle
->getVerbose())
1797 printf("Found %d custom asset file%s in %s\n",
1798 count
, (count
==1) ? "" : "s", assetDir
);
1802 * If a directory of resource-specific assets was supplied, slurp 'em up.
1804 for (size_t i
=0; i
<dirCount
; i
++) {
1805 const char *res
= resDirs
[i
];
1807 type
= getFileType(res
);
1808 if (type
== kFileTypeNonexistent
) {
1809 fprintf(stderr
, "ERROR: resource directory '%s' does not exist\n", res
);
1810 return UNKNOWN_ERROR
;
1812 if (type
== kFileTypeDirectory
) {
1814 sp
<AaptAssets
> nextOverlay
= new AaptAssets();
1815 current
->setOverlay(nextOverlay
);
1816 current
= nextOverlay
;
1818 count
= current
->slurpResourceTree(bundle
, String8(res
));
1824 totalCount
+= count
;
1827 fprintf(stderr
, "ERROR: '%s' is not a directory\n", res
);
1828 return UNKNOWN_ERROR
;
1834 * Now do any additional raw files.
1836 for (int arg
=0; arg
<N
; arg
++) {
1837 const char* assetDir
= bundle
->getFileSpecEntry(arg
);
1839 FileType type
= getFileType(assetDir
);
1840 if (type
== kFileTypeNonexistent
) {
1841 fprintf(stderr
, "ERROR: input directory '%s' does not exist\n", assetDir
);
1842 return UNKNOWN_ERROR
;
1844 if (type
!= kFileTypeDirectory
) {
1845 fprintf(stderr
, "ERROR: '%s' is not a directory\n", assetDir
);
1846 return UNKNOWN_ERROR
;
1849 String8
assetRoot(assetDir
);
1851 if (bundle
->getVerbose())
1852 printf("Processing raw dir '%s'\n", (const char*) assetDir
);
1855 * Do a recursive traversal of subdir tree. We don't make any
1856 * guarantees about ordering, so we're okay with an inorder search
1857 * using whatever order the OS happens to hand back to us.
1859 count
= slurpFullTree(bundle
, assetRoot
, AaptGroupEntry(), String8());
1861 /* failure; report error and remove archive */
1865 totalCount
+= count
;
1867 if (bundle
->getVerbose())
1868 printf("Found %d asset file%s in %s\n",
1869 count
, (count
==1) ? "" : "s", assetDir
);
1873 if (count
!= NO_ERROR
) {
1883 ssize_t
AaptAssets::slurpFullTree(Bundle
* bundle
, const String8
& srcDir
,
1884 const AaptGroupEntry
& kind
,
1885 const String8
& resType
)
1887 ssize_t res
= AaptDir::slurpFullTree(bundle
, srcDir
, kind
, resType
);
1889 mGroupEntries
.add(kind
);
1895 ssize_t
AaptAssets::slurpResourceTree(Bundle
* bundle
, const String8
& srcDir
)
1899 DIR* dir
= opendir(srcDir
.string());
1901 fprintf(stderr
, "ERROR: opendir(%s): %s\n", srcDir
.string(), strerror(errno
));
1902 return UNKNOWN_ERROR
;
1908 * Run through the directory, looking for dirs that match the
1912 struct dirent
* entry
= readdir(dir
);
1913 if (entry
== NULL
) {
1917 if (isHidden(srcDir
.string(), entry
->d_name
)) {
1921 String8
subdirName(srcDir
);
1922 subdirName
.appendPath(entry
->d_name
);
1924 AaptGroupEntry group
;
1926 bool b
= group
.initFromDirName(entry
->d_name
, &resType
);
1928 fprintf(stderr
, "invalid resource directory name: %s/%s\n", srcDir
.string(),
1934 if (bundle
->getMaxResVersion() != NULL
&& group
.version
.length() != 0) {
1935 int maxResInt
= atoi(bundle
->getMaxResVersion());
1936 const char *verString
= group
.version
.string();
1937 int dirVersionInt
= atoi(verString
+ 1); // skip 'v' in version name
1938 if (dirVersionInt
> maxResInt
) {
1939 fprintf(stderr
, "max res %d, skipping %s\n", maxResInt
, entry
->d_name
);
1944 FileType type
= getFileType(subdirName
.string());
1946 if (type
== kFileTypeDirectory
) {
1947 sp
<AaptDir
> dir
= makeDir(String8(entry
->d_name
));
1948 ssize_t res
= dir
->slurpFullTree(bundle
, subdirName
, group
,
1955 mGroupEntries
.add(group
);
1961 if (bundle
->getVerbose()) {
1962 fprintf(stderr
, " (ignoring file '%s')\n", subdirName
.string());
1978 AaptAssets::slurpResourceZip(Bundle
* bundle
, const char* filename
)
1981 SortedVector
<AaptGroupEntry
> entries
;
1983 ZipFile
* zip
= new ZipFile
;
1984 status_t err
= zip
->open(filename
, ZipFile::kOpenReadOnly
);
1985 if (err
!= NO_ERROR
) {
1986 fprintf(stderr
, "error opening zip file %s\n", filename
);
1992 const int N
= zip
->getNumEntries();
1993 for (int i
=0; i
<N
; i
++) {
1994 ZipEntry
* entry
= zip
->getEntryByIndex(i
);
1995 if (entry
->getDeleted()) {
1999 String8
entryName(entry
->getFileName());
2001 String8 dirName
= entryName
.getPathDir();
2002 sp
<AaptDir
> dir
= dirName
== "" ? this : makeDir(dirName
);
2005 AaptGroupEntry kind
;
2008 if (entryName
.walkPath(&remain
) == kResourceDir
) {
2009 // these are the resources, pull their type out of the directory name
2010 kind
.initFromDirName(remain
.walkPath().string(), &resType
);
2012 // these are untyped and don't have an AaptGroupEntry
2014 if (entries
.indexOf(kind
) < 0) {
2016 mGroupEntries
.add(kind
);
2019 // use the one from the zip file if they both exist.
2020 dir
->removeFile(entryName
.getPathLeaf());
2022 sp
<AaptFile
> file
= new AaptFile(entryName
, kind
, resType
);
2023 status_t err
= dir
->addLeafFile(entryName
.getPathLeaf(), file
);
2024 if (err
!= NO_ERROR
) {
2025 fprintf(stderr
, "err=%s entryName=%s\n", strerror(err
), entryName
.string());
2029 file
->setCompressionMethod(entry
->getCompressionMethod());
2032 if (entryName
== "AndroidManifest.xml") {
2033 printf("AndroidManifest.xml\n");
2035 printf("\n\nfile: %s\n", entryName
.string());
2038 size_t len
= entry
->getUncompressedLen();
2039 void* data
= zip
->uncompress(entry
);
2040 void* buf
= file
->editData(len
);
2041 memcpy(buf
, data
, len
);
2045 const unsigned char* p
= (unsigned char*)data
;
2046 const unsigned char* end
= p
+len
;
2048 for (int i
=0; i
<32 && p
< end
; i
++) {
2049 printf("0x%03x ", i
*0x10 + OFF
);
2050 for (int j
=0; j
<0x10 && p
< end
; j
++) {
2051 printf(" %02x", *p
);
2068 sp
<AaptSymbols
> AaptAssets::getSymbolsFor(const String8
& name
)
2070 sp
<AaptSymbols
> sym
= mSymbols
.valueFor(name
);
2072 sym
= new AaptSymbols();
2073 mSymbols
.add(name
, sym
);
2078 status_t
AaptAssets::buildIncludedResources(Bundle
* bundle
)
2080 if (!mHaveIncludedAssets
) {
2081 // Add in all includes.
2082 const Vector
<const char*>& incl
= bundle
->getPackageIncludes();
2083 const size_t N
=incl
.size();
2084 for (size_t i
=0; i
<N
; i
++) {
2085 if (bundle
->getVerbose())
2086 printf("Including resources from package: %s\n", incl
[i
]);
2087 if (!mIncludedAssets
.addAssetPath(String8(incl
[i
]), NULL
)) {
2088 fprintf(stderr
, "ERROR: Asset package include '%s' not found.\n",
2090 return UNKNOWN_ERROR
;
2093 mHaveIncludedAssets
= true;
2099 status_t
AaptAssets::addIncludedResources(const sp
<AaptFile
>& file
)
2101 const ResTable
& res
= getIncludedResources();
2103 return const_cast<ResTable
&>(res
).add(file
->getData(), file
->getSize(), NULL
);
2106 const ResTable
& AaptAssets::getIncludedResources() const
2108 return mIncludedAssets
.getResources(false);
2111 void AaptAssets::print() const
2113 printf("Locale/Vendor pairs:\n");
2114 const size_t N
=mGroupEntries
.size();
2115 for (size_t i
=0; i
<N
; i
++) {
2117 mGroupEntries
.itemAt(i
).locale
.string(),
2118 mGroupEntries
.itemAt(i
).vendor
.string());
2121 printf("\nFiles:\n");
2125 sp
<AaptDir
> AaptAssets::resDir(const String8
& name
)
2127 const Vector
<sp
<AaptDir
> >& dirs
= mDirs
;
2128 const size_t N
= dirs
.size();
2129 for (size_t i
=0; i
<N
; i
++) {
2130 const sp
<AaptDir
>& d
= dirs
.itemAt(i
);
2131 if (d
->getLeaf() == name
) {
2139 valid_symbol_name(const String8
& symbol
)
2141 static char const * const KEYWORDS
[] = {
2142 "abstract", "assert", "boolean", "break",
2143 "byte", "case", "catch", "char", "class", "const", "continue",
2144 "default", "do", "double", "else", "enum", "extends", "final",
2145 "finally", "float", "for", "goto", "if", "implements", "import",
2146 "instanceof", "int", "interface", "long", "native", "new", "package",
2147 "private", "protected", "public", "return", "short", "static",
2148 "strictfp", "super", "switch", "synchronized", "this", "throw",
2149 "throws", "transient", "try", "void", "volatile", "while",
2150 "true", "false", "null",
2153 const char*const* k
= KEYWORDS
;
2154 const char*const s
= symbol
.string();
2156 if (0 == strcmp(s
, *k
)) {