]> git.saurik.com Git - android/aapt.git/blobdiff - AaptAssets.cpp
Cache resource ID lookups in aapt
[android/aapt.git] / AaptAssets.cpp
index f0c215eeffa5ce686d2059744a1ec047ba944793..5b71adc81cbe09d89abb9223bd4906abf2e79476 100644 (file)
@@ -56,55 +56,93 @@ static bool validateFileName(const char* fileName)
     return true;
 }
 
     return true;
 }
 
+// The default to use if no other ignore pattern is defined.
+const char * const gDefaultIgnoreAssets =
+    "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~";
+// The ignore pattern that can be passed via --ignore-assets in Main.cpp
+const char * gUserIgnoreAssets = NULL;
+
 static bool isHidden(const char *root, const char *path)
 {
 static bool isHidden(const char *root, const char *path)
 {
-    const char *ext  = NULL;
-    const char *type = NULL;
-
-    // Skip all hidden files.
-    if (path[0] == '.') {
-        // Skip ., .. and  .svn but don't chatter about it.
-        if (strcmp(path, ".") == 0
-            || strcmp(path, "..") == 0
-            || strcmp(path, ".svn") == 0) {
-            return true;
-        }
-        type = "hidden";
-    } else if (path[0] == '_') {
-        // skip directories starting with _ (don't chatter about it)
-        String8 subdirName(root);
-        subdirName.appendPath(path);
-        if (getFileType(subdirName.string()) == kFileTypeDirectory) {
-            return true;
-        }
-    } else if (strcmp(path, "CVS") == 0) {
-        // Skip CVS but don't chatter about it.
-        return true;
-    } else if (strcasecmp(path, "thumbs.db") == 0
-               || strcasecmp(path, "picasa.ini") == 0) {
-        // Skip suspected image indexes files.
-        type = "index";
-    } else if (path[strlen(path)-1] == '~') {
-        // Skip suspected emacs backup files.
-        type = "backup";
-    } else if ((ext = strrchr(path, '.')) != NULL && strcmp(ext, ".scc") == 0) {
-        // Skip VisualSourceSafe files and don't chatter about it
+    // Patterns syntax:
+    // - Delimiter is :
+    // - Entry can start with the flag ! to avoid printing a warning
+    //   about the file being ignored.
+    // - Entry can have the flag "<dir>" to match only directories
+    //   or <file> to match only files. Default is to match both.
+    // - Entry can be a simplified glob "<prefix>*" or "*<suffix>"
+    //   where prefix/suffix must have at least 1 character (so that
+    //   we don't match a '*' catch-all pattern.)
+    // - The special filenames "." and ".." are always ignored.
+    // - Otherwise the full string is matched.
+    // - match is not case-sensitive.
+
+    if (strcmp(path, ".") == 0 || strcmp(path, "..") == 0) {
         return true;
         return true;
-    } else {
-        // Let everything else through.
-        return false;
     }
 
     }
 
-    /* If we get this far, "type" should be set and the file
-     * should be skipped.
-     */
-    String8 subdirName(root);
-    subdirName.appendPath(path);
-    fprintf(stderr, "    (skipping %s %s '%s')\n", type,
-            getFileType(subdirName.string())==kFileTypeDirectory ? "dir":"file",
-            subdirName.string());
+    const char *delim = ":";
+    const char *p = gUserIgnoreAssets;
+    if (!p || !p[0]) {
+        p = getenv("ANDROID_AAPT_IGNORE");
+    }
+    if (!p || !p[0]) {
+        p = gDefaultIgnoreAssets;
+    }
+    char *patterns = strdup(p);
 
 
-    return true;
+    bool ignore = false;
+    bool chatty = true;
+    char *matchedPattern = NULL;
+
+    String8 fullPath(root);
+    fullPath.appendPath(path);
+    FileType type = getFileType(fullPath);
+
+    int plen = strlen(path);
+
+    // Note: we don't have strtok_r under mingw.
+    for(char *token = strtok(patterns, delim);
+            !ignore && token != NULL;
+            token = strtok(NULL, delim)) {
+        chatty = token[0] != '!';
+        if (!chatty) token++; // skip !
+        if (strncasecmp(token, "<dir>" , 5) == 0) {
+            if (type != kFileTypeDirectory) continue;
+            token += 5;
+        }
+        if (strncasecmp(token, "<file>", 6) == 0) {
+            if (type != kFileTypeRegular) continue;
+            token += 6;
+        }
+
+        matchedPattern = token;
+        int n = strlen(token);
+
+        if (token[0] == '*') {
+            // Match *suffix
+            token++;
+            n--;
+            if (n <= plen) {
+                ignore = strncasecmp(token, path + plen - n, n) == 0;
+            }
+        } else if (n > 1 && token[n - 1] == '*') {
+            // Match prefix*
+            ignore = strncasecmp(token, path, n - 1) == 0;
+        } else {
+            ignore = strcasecmp(token, path) == 0;
+        }
+    }
+
+    if (ignore && chatty) {
+        fprintf(stderr, "    (skipping %s '%s' due to ANDROID_AAPT_IGNORE pattern '%s')\n",
+                type == kFileTypeDirectory ? "dir" : "file",
+                path,
+                matchedPattern ? matchedPattern : "");
+    }
+
+    free(patterns);
+    return ignore;
 }
 
 // =========================================================================
 }
 
 // =========================================================================
@@ -145,6 +183,13 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
         return 0;
     }
 
         return 0;
     }
 
+    // layout direction
+    if (getLayoutDirectionName(part.string(), &config)) {
+        *axis = AXIS_LAYOUTDIR;
+        *value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
+        return 0;
+    }
+
     // smallest screen dp width
     if (getSmallestScreenWidthDpName(part.string(), &config)) {
         *axis = AXIS_SMALLESTSCREENWIDTHDP;
     // smallest screen dp width
     if (getSmallestScreenWidthDpName(part.string(), &config)) {
         *axis = AXIS_SMALLESTSCREENWIDTHDP;
@@ -271,6 +316,8 @@ AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis)
         case AXIS_LANGUAGE:
             return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
                 | (((uint32_t)config.language[1]) << 8) | (config.language[0]);
         case AXIS_LANGUAGE:
             return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
                 | (((uint32_t)config.language[1]) << 8) | (config.language[0]);
+        case AXIS_LAYOUTDIR:
+            return config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
         case AXIS_SCREENLAYOUTSIZE:
             return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
         case AXIS_ORIENTATION:
         case AXIS_SCREENLAYOUTSIZE:
             return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
         case AXIS_ORIENTATION:
@@ -326,7 +373,7 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
     Vector<String8> parts;
 
     String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
     Vector<String8> parts;
 
     String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
-    String8 touch, key, keysHidden, nav, navHidden, size, vers;
+    String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers;
     String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
 
     const char *p = dir;
     String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
 
     const char *p = dir;
@@ -414,6 +461,18 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
         //printf("not region: %s\n", part.string());
     }
 
         //printf("not region: %s\n", part.string());
     }
 
+    if (getLayoutDirectionName(part.string())) {
+        layoutDir = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not layout direction: %s\n", part.string());
+    }
+
     if (getSmallestScreenWidthDpName(part.string())) {
         smallestwidthdp = part;
 
     if (getSmallestScreenWidthDpName(part.string())) {
         smallestwidthdp = part;
 
@@ -636,6 +695,7 @@ success:
     this->navHidden = navHidden;
     this->navigation = nav;
     this->screenSize = size;
     this->navHidden = navHidden;
     this->navigation = nav;
     this->screenSize = size;
+    this->layoutDirection = layoutDir;
     this->version = vers;
 
     // what is this anyway?
     this->version = vers;
 
     // what is this anyway?
@@ -653,6 +713,8 @@ AaptGroupEntry::toString() const
     s += ",";
     s += this->locale;
     s += ",";
     s += ",";
     s += this->locale;
     s += ",";
+    s += layoutDirection;
+    s += ",";
     s += smallestScreenWidthDp;
     s += ",";
     s += screenWidthDp;
     s += smallestScreenWidthDp;
     s += ",";
     s += screenWidthDp;
@@ -709,6 +771,12 @@ AaptGroupEntry::toDirName(const String8& resType) const
         }
         s += locale;
     }
         }
         s += locale;
     }
+    if (this->layoutDirection != "") {
+        if (s.length() > 0) {
+            s += "-";
+        }
+        s += layoutDirection;
+    }
     if (this->smallestScreenWidthDp != "") {
         if (s.length() > 0) {
             s += "-";
     if (this->smallestScreenWidthDp != "") {
         if (s.length() > 0) {
             s += "-";
@@ -920,6 +988,28 @@ bool AaptGroupEntry::getLocaleName(const char* fileName,
     return false;
 }
 
     return false;
 }
 
+bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_ANY;
+        return true;
+    } else if (strcmp(name, "ldltr") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_LTR;
+        return true;
+    } else if (strcmp(name, "ldrtl") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_RTL;
+        return true;
+    }
+
+    return false;
+}
+
 bool AaptGroupEntry::getScreenLayoutSizeName(const char* name,
                                      ResTable_config* out)
 {
 bool AaptGroupEntry::getScreenLayoutSizeName(const char* name,
                                      ResTable_config* out)
 {
@@ -1084,12 +1174,17 @@ bool AaptGroupEntry::getDensityName(const char* name,
         if (out) out->density = ResTable_config::DENSITY_HIGH;
         return true;
     }
         if (out) out->density = ResTable_config::DENSITY_HIGH;
         return true;
     }
-    
+
     if (strcmp(name, "xhdpi") == 0) {
     if (strcmp(name, "xhdpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_MEDIUM*2;
+        if (out) out->density = ResTable_config::DENSITY_XHIGH;
         return true;
     }
         return true;
     }
-    
+
+    if (strcmp(name, "xxhdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_XXHIGH;
+        return true;
+    }
+
     char* c = (char*)name;
     while (*c >= '0' && *c <= '9') {
         c++;
     char* c = (char*)name;
     while (*c >= '0' && *c <= '9') {
         c++;
@@ -1372,6 +1467,7 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const
     int v = mcc.compare(o.mcc);
     if (v == 0) v = mnc.compare(o.mnc);
     if (v == 0) v = locale.compare(o.locale);
     int v = mcc.compare(o.mcc);
     if (v == 0) v = mnc.compare(o.mnc);
     if (v == 0) v = locale.compare(o.locale);
+    if (v == 0) v = layoutDirection.compare(o.layoutDirection);
     if (v == 0) v = vendor.compare(o.vendor);
     if (v == 0) v = smallestScreenWidthDp.compare(o.smallestScreenWidthDp);
     if (v == 0) v = screenWidthDp.compare(o.screenWidthDp);
     if (v == 0) v = vendor.compare(o.vendor);
     if (v == 0) v = smallestScreenWidthDp.compare(o.smallestScreenWidthDp);
     if (v == 0) v = screenWidthDp.compare(o.screenWidthDp);
@@ -1404,6 +1500,7 @@ const ResTable_config& AaptGroupEntry::toParams() const
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
     getLocaleName(locale.string(), &params);
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
     getLocaleName(locale.string(), &params);
+    getLayoutDirectionName(layoutDirection.string(), &params);
     getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), &params);
     getScreenWidthDpName(screenWidthDp.string(), &params);
     getScreenHeightDpName(screenHeightDp.string(), &params);
     getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), &params);
     getScreenWidthDpName(screenWidthDp.string(), &params);
     getScreenHeightDpName(screenHeightDp.string(), &params);
@@ -1832,6 +1929,49 @@ String8 AaptDir::getPrintableSource() const
 // =========================================================================
 // =========================================================================
 
 // =========================================================================
 // =========================================================================
 
+status_t AaptSymbols::applyJavaSymbols(const sp<AaptSymbols>& javaSymbols)
+{
+    status_t err = NO_ERROR;
+    size_t N = javaSymbols->mSymbols.size();
+    for (size_t i=0; i<N; i++) {
+        const String8& name = javaSymbols->mSymbols.keyAt(i);
+        const AaptSymbolEntry& entry = javaSymbols->mSymbols.valueAt(i);
+        ssize_t pos = mSymbols.indexOfKey(name);
+        if (pos < 0) {
+            entry.sourcePos.error("Symbol '%s' declared with <java-symbol> not defined\n", name.string());
+            err = UNKNOWN_ERROR;
+            continue;
+        }
+        //printf("**** setting symbol #%d/%d %s to isJavaSymbol=%d\n",
+        //        i, N, name.string(), entry.isJavaSymbol ? 1 : 0);
+        mSymbols.editValueAt(pos).isJavaSymbol = entry.isJavaSymbol;
+    }
+
+    N = javaSymbols->mNestedSymbols.size();
+    for (size_t i=0; i<N; i++) {
+        const String8& name = javaSymbols->mNestedSymbols.keyAt(i);
+        const sp<AaptSymbols>& symbols = javaSymbols->mNestedSymbols.valueAt(i);
+        ssize_t pos = mNestedSymbols.indexOfKey(name);
+        if (pos < 0) {
+            SourcePos pos;
+            pos.error("Java symbol dir %s not defined\n", name.string());
+            err = UNKNOWN_ERROR;
+            continue;
+        }
+        //printf("**** applying java symbols in dir %s\n", name.string());
+        status_t myerr = mNestedSymbols.valueAt(pos)->applyJavaSymbols(symbols);
+        if (myerr != NO_ERROR) {
+            err = myerr;
+        }
+    }
+
+    return err;
+}
+
+// =========================================================================
+// =========================================================================
+// =========================================================================
+
 AaptAssets::AaptAssets()
     : AaptDir(String8(), String8()),
       mChanged(false), mHaveIncludedAssets(false), mRes(NULL)
 AaptAssets::AaptAssets()
     : AaptDir(String8(), String8()),
       mChanged(false), mHaveIncludedAssets(false), mRes(NULL)
@@ -2399,6 +2539,48 @@ sp<AaptSymbols> AaptAssets::getSymbolsFor(const String8& name)
     return sym;
 }
 
     return sym;
 }
 
+sp<AaptSymbols> AaptAssets::getJavaSymbolsFor(const String8& name)
+{
+    sp<AaptSymbols> sym = mJavaSymbols.valueFor(name);
+    if (sym == NULL) {
+        sym = new AaptSymbols();
+        mJavaSymbols.add(name, sym);
+    }
+    return sym;
+}
+
+status_t AaptAssets::applyJavaSymbols()
+{
+    size_t N = mJavaSymbols.size();
+    for (size_t i=0; i<N; i++) {
+        const String8& name = mJavaSymbols.keyAt(i);
+        const sp<AaptSymbols>& symbols = mJavaSymbols.valueAt(i);
+        ssize_t pos = mSymbols.indexOfKey(name);
+        if (pos < 0) {
+            SourcePos pos;
+            pos.error("Java symbol dir %s not defined\n", name.string());
+            return UNKNOWN_ERROR;
+        }
+        //printf("**** applying java symbols in dir %s\n", name.string());
+        status_t err = mSymbols.valueAt(pos)->applyJavaSymbols(symbols);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+
+    return NO_ERROR;
+}
+
+bool AaptAssets::isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const {
+    //printf("isJavaSymbol %s: public=%d, includePrivate=%d, isJavaSymbol=%d\n",
+    //        sym.name.string(), sym.isPublic ? 1 : 0, includePrivate ? 1 : 0,
+    //        sym.isJavaSymbol ? 1 : 0);
+    if (!mHavePrivateSymbols) return true;
+    if (sym.isPublic) return true;
+    if (includePrivate && sym.isJavaSymbol) return true;
+    return false;
+}
+
 status_t AaptAssets::buildIncludedResources(Bundle* bundle)
 {
     if (!mHaveIncludedAssets) {
 status_t AaptAssets::buildIncludedResources(Bundle* bundle)
 {
     if (!mHaveIncludedAssets) {