Move String8 path functions to androidfw and aapt
Test: m checkbuild
Bug: 295394788
Change-Id: I9488bc5632cbd47c83f6b5f2df4c87eb324a1e8e
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index c80fb18..86e1fe3d 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -80,7 +80,10 @@
export_include_dirs: ["include"],
export_shared_lib_headers: ["libz"],
static_libs: ["libincfs-utils"],
- whole_static_libs: ["libincfs-utils"],
+ whole_static_libs: [
+ "libandroidfw_pathutils",
+ "libincfs-utils",
+ ],
export_static_lib_headers: ["libincfs-utils"],
target: {
android: {
@@ -132,6 +135,28 @@
},
}
+cc_library_static {
+ name: "libandroidfw_pathutils",
+ defaults: ["libandroidfw_defaults"],
+ host_supported: true,
+ export_include_dirs: ["include_pathutils"],
+ srcs: [
+ "PathUtils.cpp",
+ ],
+ shared_libs: [
+ "libutils",
+ ],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+ visibility: [
+ ":__subpackages__",
+ "//frameworks/base/tools/aapt",
+ ],
+}
+
common_test_libs = [
"libandroidfw",
"libbase",
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 795bb3c..fd6e18e 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -26,6 +26,7 @@
#include <androidfw/AssetDir.h>
#include <androidfw/AssetManager.h>
#include <androidfw/misc.h>
+#include <androidfw/PathUtils.h>
#include <androidfw/ResourceTypes.h>
#include <androidfw/ZipFileRO.h>
#include <cutils/atomic.h>
@@ -88,7 +89,7 @@
const char* root = getenv("ANDROID_DATA");
LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
String8 path(root);
- path.appendPath(kResourceCache);
+ appendPath(path, kResourceCache);
char buf[256]; // 256 chars should be enough for anyone...
strncpy(buf, pkgPath.c_str(), 255);
@@ -104,7 +105,7 @@
}
++p;
}
- path.appendPath(filename);
+ appendPath(path, filename);
path.append("@idmap");
return path;
@@ -181,7 +182,7 @@
String8 realPath(path);
if (kAppZipName) {
- realPath.appendPath(kAppZipName);
+ appendPath(realPath, kAppZipName);
}
ap.type = ::getFileType(realPath.c_str());
if (ap.type == kFileTypeRegular) {
@@ -367,7 +368,7 @@
LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set");
String8 path(root);
- path.appendPath(kSystemAssets);
+ appendPath(path, kSystemAssets);
return addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
}
@@ -439,7 +440,7 @@
LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
String8 assetName(kAssetsRoot);
- assetName.appendPath(fileName);
+ appendPath(assetName, fileName);
/*
* For each top-level asset path, search for the asset.
@@ -587,8 +588,8 @@
const char* data = getenv("ANDROID_DATA");
LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
String8 overlaysListPath(data);
- overlaysListPath.appendPath(kResourceCache);
- overlaysListPath.appendPath("overlays.list");
+ appendPath(overlaysListPath, kResourceCache);
+ appendPath(overlaysListPath, "overlays.list");
addSystemOverlays(overlaysListPath.c_str(), ap.path, sharedRes, nextEntryIdx);
#endif
sharedRes = const_cast<AssetManager*>(this)->
@@ -789,7 +790,7 @@
/* look at the filesystem on disk */
if (ap.type == kFileTypeDirectory) {
String8 path(ap.path);
- path.appendPath(fileName);
+ appendPath(path, fileName);
pAsset = openAssetFromFileLocked(path, mode);
@@ -841,9 +842,9 @@
sourceName.append(zipFileName);
sourceName.append(":");
if (dirName.length() > 0) {
- sourceName.appendPath(dirName);
+ appendPath(sourceName, dirName);
}
- sourceName.appendPath(fileName);
+ appendPath(sourceName, fileName);
return sourceName;
}
@@ -853,7 +854,7 @@
String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir)
{
String8 path(ap.path);
- if (rootDir != NULL) path.appendPath(rootDir);
+ if (rootDir != NULL) appendPath(path, rootDir);
return path;
}
@@ -897,7 +898,7 @@
{
Asset* pAsset = NULL;
- if (strcasecmp(pathName.getPathExtension().c_str(), ".gz") == 0) {
+ if (strcasecmp(getPathExtension(pathName).c_str(), ".gz") == 0) {
//printf("TRYING '%s'\n", (const char*) pathName);
pAsset = Asset::createFromCompressedFile(pathName.c_str(), mode);
} else {
@@ -1078,8 +1079,7 @@
//printf("scanAndMergeDir: %s %s %s\n", ap.path.c_str(), rootDir, dirName);
String8 path = createPathNameLocked(ap, rootDir);
- if (dirName[0] != '\0')
- path.appendPath(dirName);
+ if (dirName[0] != '\0') appendPath(path, dirName);
SortedVector<AssetDir::FileInfo>* pContents = scanDirLocked(path);
if (pContents == NULL)
@@ -1176,7 +1176,7 @@
fileType = kFileTypeUnknown;
#else
// stat the file
- fileType = ::getFileType(path.appendPathCopy(entry->d_name).c_str());
+ fileType = ::getFileType(appendPathCopy(path, entry->d_name).c_str());
#endif
if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory)
@@ -1184,9 +1184,9 @@
AssetDir::FileInfo info;
info.set(String8(entry->d_name), fileType);
- if (strcasecmp(info.getFileName().getPathExtension().c_str(), ".gz") == 0)
- info.setFileName(info.getFileName().getBasePath());
- info.setSourceName(path.appendPathCopy(info.getFileName()));
+ if (strcasecmp(getPathExtension(info.getFileName()).c_str(), ".gz") == 0)
+ info.setFileName(getBasePath(info.getFileName()));
+ info.setSourceName(appendPathCopy(path, info.getFileName()));
pContents->add(info);
}
@@ -1220,7 +1220,7 @@
/* convert "sounds" to "rootDir/sounds" */
if (rootDir != NULL) dirName = rootDir;
- dirName.appendPath(baseDirName);
+ appendPath(dirName, baseDirName);
/*
* Scan through the list of files, looking for a match. The files in
@@ -1269,7 +1269,7 @@
if (nextSlash == NULL) {
/* this is a file in the requested directory */
- info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular);
+ info.set(getPathLeaf(String8(nameBuf)), kFileTypeRegular);
info.setSourceName(
createZipSourceNameLocked(zipName, dirName, info.getFileName()));
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index 3582609..1a6a952 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -30,6 +30,7 @@
#include <utime.h>
#include <zlib.h>
+#include <androidfw/PathUtils.h>
#include <log/log.h>
#include <utils/ByteOrder.h>
#include <utils/KeyedVector.h>
@@ -606,14 +607,14 @@
prefix += packageName;
}
if (domain.length() > 0) {
- prefix.appendPath(domain);
+ appendPath(prefix, domain);
}
// pax extended means we don't put in a prefix field, and put a different
// string in the basic name field. We can also construct the full path name
// out of the substrings we've now built.
fullname = prefix;
- fullname.appendPath(relpath);
+ appendPath(fullname, relpath);
// ustar:
// [ 0 : 100 ]; file name/path
@@ -654,7 +655,7 @@
// Now build the pax *header* templated on the ustar header
memcpy(paxHeader, buf, 512);
- String8 leaf = fullname.getPathLeaf();
+ String8 leaf = getPathLeaf(fullname);
memset(paxHeader, 0, 100); // rewrite the name area
snprintf(paxHeader, 100, "PaxHeader/%s", leaf.c_str());
memset(paxHeader + 345, 0, 155); // rewrite the prefix area
diff --git a/libs/androidfw/PathUtils.cpp b/libs/androidfw/PathUtils.cpp
new file mode 100644
index 0000000..df7a9f0
--- /dev/null
+++ b/libs/androidfw/PathUtils.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/PathUtils.h>
+
+#include <utils/Compat.h>
+
+namespace android {
+
+String8 getPathLeaf(const String8& str) {
+ const char* cp;
+ const char*const buf = str.c_str();
+
+ cp = strrchr(buf, OS_PATH_SEPARATOR);
+ if (cp == nullptr)
+ return str;
+ else
+ return String8(cp+1);
+}
+
+String8 getPathDir(const String8& str8) {
+ const char* cp;
+ const char*const str = str8.c_str();
+
+ cp = strrchr(str, OS_PATH_SEPARATOR);
+ if (cp == nullptr)
+ return String8();
+ else
+ return String8(str, cp - str);
+}
+
+static char* findExtension(const String8& str8) {
+ const char* lastSlash;
+ const char* lastDot;
+ const char* const str = str8.c_str();
+
+ // only look at the filename
+ lastSlash = strrchr(str, OS_PATH_SEPARATOR);
+ if (lastSlash == nullptr)
+ lastSlash = str;
+ else
+ lastSlash++;
+
+ // find the last dot
+ lastDot = strrchr(lastSlash, '.');
+ if (lastDot == nullptr)
+ return nullptr;
+
+ // looks good, ship it
+ return const_cast<char*>(lastDot);
+}
+
+String8 getPathExtension(const String8& str) {
+ char* ext;
+
+ ext = findExtension(str);
+ if (ext != nullptr)
+ return String8(ext);
+ else
+ return String8();
+}
+
+String8 getBasePath(const String8& str8) {
+ char* ext;
+ const char* const str = str8.c_str();
+
+ ext = findExtension(str8);
+ if (ext == nullptr)
+ return str8;
+ else
+ return String8(str, ext - str);
+}
+
+static void setPathName(String8& s, const char* name) {
+ size_t len = strlen(name);
+ char* buf = s.lockBuffer(len);
+
+ memcpy(buf, name, len);
+
+ // remove trailing path separator, if present
+ if (len > 0 && buf[len - 1] == OS_PATH_SEPARATOR) len--;
+ buf[len] = '\0';
+
+ s.unlockBuffer(len);
+}
+
+String8& appendPath(String8& str, const char* name) {
+ // TODO: The test below will fail for Win32 paths. Fix later or ignore.
+ if (name[0] != OS_PATH_SEPARATOR) {
+ if (*name == '\0') {
+ // nothing to do
+ return str;
+ }
+
+ size_t len = str.length();
+ if (len == 0) {
+ // no existing filename, just use the new one
+ setPathName(str, name);
+ return str;
+ }
+
+ // make room for oldPath + '/' + newPath
+ int newlen = strlen(name);
+
+ char* buf = str.lockBuffer(len+1+newlen);
+
+ // insert a '/' if needed
+ if (buf[len-1] != OS_PATH_SEPARATOR)
+ buf[len++] = OS_PATH_SEPARATOR;
+
+ memcpy(buf+len, name, newlen+1);
+ len += newlen;
+
+ str.unlockBuffer(len);
+ return str;
+ } else {
+ setPathName(str, name);
+ return str;
+ }
+}
+
+} // namespace android
diff --git a/libs/androidfw/include_pathutils/androidfw/PathUtils.h b/libs/androidfw/include_pathutils/androidfw/PathUtils.h
new file mode 100644
index 0000000..4debe8d
--- /dev/null
+++ b/libs/androidfw/include_pathutils/androidfw/PathUtils.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/String8.h>
+
+/* This library contains path manipulation functions that are used only by androidfw and aapt.
+ * When it's possible, migrate all uses to std::filesystem::path.
+ */
+
+namespace android {
+
+/**
+ * Get just the filename component.
+ *
+ * DEPRECATED: use std::filesystem::path::filename
+ *
+ * "/tmp/foo/bar.c" --> "bar.c"
+ */
+String8 getPathLeaf(const String8& str);
+
+/**
+ * Remove the last (file name) component, leaving just the directory
+ * name.
+ *
+ * DEPRECATED: use std::filesystem::path::parent_path
+ *
+ * "/tmp/foo/bar.c" --> "/tmp/foo"
+ * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX
+ * "bar.c" --> ""
+ */
+String8 getPathDir(const String8& str);
+
+/**
+ * Return the filename extension. This is the last '.' and any number
+ * of characters that follow it. The '.' is included in case we
+ * decide to expand our definition of what constitutes an extension.
+ *
+ * DEPRECATED: use std::filesystem::path::extension
+ *
+ * "/tmp/foo/bar.c" --> ".c"
+ * "/tmp" --> ""
+ * "/tmp/foo.bar/baz" --> ""
+ * "foo.jpeg" --> ".jpeg"
+ * "foo." --> ""
+ */
+String8 getPathExtension(const String8& str);
+
+/**
+ * Return the path without the extension. Rules for what constitutes
+ * an extension are described in the comment for getPathExtension().
+ *
+ * DEPRECATED: use std::filesystem::path::stem and std::filesystem::path::parent_path
+ *
+ * "/tmp/foo/bar.c" --> "/tmp/foo/bar"
+ */
+String8 getBasePath(const String8& str);
+
+/**
+ * Add a component to the pathname. We guarantee that there is
+ * exactly one path separator between the old path and the new.
+ * If there is no existing name, we just copy the new name in.
+ *
+ * DEPRECATED: use std::filesystem::path::operator/=
+ *
+ * If leaf is a fully qualified path (i.e. starts with '/', it
+ * replaces whatever was there before.
+ */
+String8& appendPath(String8& str, const char* leaf);
+inline String8& appendPath(String8& str, const String8& leaf) {
+ return appendPath(str, leaf.c_str());
+}
+
+/**
+ * Like appendPath(), but does not affect this string. Returns a new one instead.
+ *
+ * DEPRECATED: use std::filesystem::operator/
+ */
+inline String8 appendPathCopy(String8 str, const char* leaf) { return appendPath(str, leaf); }
+inline String8 appendPathCopy(String8 str, const String8& leaf) {
+ return appendPath(str, leaf.c_str());
+}
+
+} // namespace android
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 0fc2617..0aaf3e8 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -7,7 +7,9 @@
#include "AaptUtil.h"
#include "Main.h"
#include "ResourceFilter.h"
+#include "Utils.h"
+#include <androidfw/PathUtils.h>
#include <utils/misc.h>
#include <utils/SortedVector.h>
@@ -96,7 +98,7 @@
char *matchedPattern = NULL;
String8 fullPath(root);
- fullPath.appendPath(path);
+ appendPath(fullPath, String8(path));
FileType type = getFileType(fullPath);
int plen = strlen(path);
@@ -508,7 +510,7 @@
{
if (hasData()) {
String8 name(mGroupEntry.toDirName(String8()));
- name.appendPath(mPath);
+ appendPath(name, mPath);
name.append(" #generated");
return name;
}
@@ -615,7 +617,7 @@
String8 remain = path;
sp<AaptDir> subdir = this;
- while (name = remain.walkPath(&remain), remain != "") {
+ while (name = walkPath(remain, &remain), remain != "") {
subdir = subdir->makeDir(name);
}
@@ -623,7 +625,7 @@
if (i >= 0) {
return subdir->mDirs.valueAt(i);
}
- sp<AaptDir> dir = new AaptDir(name, subdir->mPath.appendPathCopy(name));
+ sp<AaptDir> dir = new AaptDir(name, appendPathCopy(subdir->mPath, name));
subdir->mDirs.add(name, dir);
return dir;
}
@@ -645,7 +647,7 @@
if (mFiles.indexOfKey(leafName) >= 0) {
group = mFiles.valueFor(leafName);
} else {
- group = new AaptGroup(leafName, mPath.appendPathCopy(leafName));
+ group = new AaptGroup(leafName, appendPathCopy(mPath, leafName));
mFiles.add(leafName, group);
}
@@ -684,7 +686,7 @@
// Add fully qualified path for dependency purposes
// if we're collecting them
if (fullResPaths != NULL) {
- fullResPaths->add(srcDir.appendPathCopy(name));
+ fullResPaths->add(appendPathCopy(srcDir, name));
}
}
closedir(dir);
@@ -701,7 +703,7 @@
String8 pathName(srcDir);
FileType type;
- pathName.appendPath(fileNames[i].c_str());
+ appendPath(pathName, fileNames[i]);
type = getFileType(pathName.c_str());
if (type == kFileTypeDirectory) {
sp<AaptDir> subdir;
@@ -709,7 +711,7 @@
if (mDirs.indexOfKey(fileNames[i]) >= 0) {
subdir = mDirs.valueFor(fileNames[i]);
} else {
- subdir = new AaptDir(fileNames[i], mPath.appendPathCopy(fileNames[i]));
+ subdir = new AaptDir(fileNames[i], appendPathCopy(mPath, fileNames[i]));
notAdded = true;
}
ssize_t res = subdir->slurpFullTree(bundle, pathName, kind,
@@ -821,11 +823,11 @@
{
if (mFiles.size() > 0) {
// Arbitrarily pull the first file out of the list as the source dir.
- return mFiles.valueAt(0)->getPrintableSource().getPathDir();
+ return getPathDir(mFiles.valueAt(0)->getPrintableSource());
}
if (mDirs.size() > 0) {
// Or arbitrarily pull the first dir out of the list as the source dir.
- return mDirs.valueAt(0)->getPrintableSource().getPathDir();
+ return getPathDir(mDirs.valueAt(0)->getPrintableSource());
}
// Should never hit this case, but to be safe...
@@ -908,8 +910,8 @@
sp<AaptFile> file;
String8 root, remain(filePath), partialPath;
while (remain.length() > 0) {
- root = remain.walkPath(&remain);
- partialPath.appendPath(root);
+ root = walkPath(remain, &remain);
+ appendPath(partialPath, root);
const String8 rootStr(root);
@@ -924,7 +926,7 @@
return NULL;
}
}
- file = new AaptFile(srcDir.appendPathCopy(filePath), entry, resType);
+ file = new AaptFile(appendPathCopy(srcDir, filePath), entry, resType);
status_t res = group->addFile(file);
if (res != NO_ERROR) {
return NULL;
@@ -981,7 +983,7 @@
if (bundle->getAndroidManifestFile() != NULL) {
// place at root of zip.
String8 srcFile(bundle->getAndroidManifestFile());
- addFile(srcFile.getPathLeaf(), AaptGroupEntry(), srcFile.getPathDir(),
+ addFile(getPathLeaf(srcFile), AaptGroupEntry(), getPathDir(srcFile),
NULL, String8());
totalCount++;
}
@@ -1154,7 +1156,7 @@
}
String8 subdirName(srcDir);
- subdirName.appendPath(entry->d_name);
+ appendPath(subdirName, entry->d_name);
AaptGroupEntry group;
String8 resType;
@@ -1239,16 +1241,16 @@
String8 entryName(entry->getFileName());
- String8 dirName = entryName.getPathDir();
+ String8 dirName = getPathDir(entryName);
sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName);
String8 resType;
AaptGroupEntry kind;
String8 remain;
- if (entryName.walkPath(&remain) == kResourceDir) {
+ if (walkPath(entryName, &remain) == kResourceDir) {
// these are the resources, pull their type out of the directory name
- kind.initFromDirName(remain.walkPath().c_str(), &resType);
+ kind.initFromDirName(walkPath(remain).c_str(), &resType);
} else {
// these are untyped and don't have an AaptGroupEntry
}
@@ -1258,10 +1260,10 @@
}
// use the one from the zip file if they both exist.
- dir->removeFile(entryName.getPathLeaf());
+ dir->removeFile(getPathLeaf(entryName));
sp<AaptFile> file = new AaptFile(entryName, kind, resType);
- status_t err = dir->addLeafFile(entryName.getPathLeaf(), file);
+ status_t err = dir->addLeafFile(getPathLeaf(entryName), file);
if (err != NO_ERROR) {
fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.c_str());
count = err;
@@ -1374,7 +1376,7 @@
// containing no entries.
continue;
}
- if (file->getPath().getPathExtension() == ".xml") {
+ if (getPathExtension(file->getPath()) == ".xml") {
// We can't remove .xml files at this point, because when
// we parse them they may add identifier resources, so
// removing them can cause our resource identifiers to
@@ -1411,7 +1413,7 @@
// containing no entries.
continue;
}
- if (file->getPath().getPathExtension() == ".xml") {
+ if (getPathExtension(file->getPath()) == ".xml") {
// We can't remove .xml files at this point, because when
// we parse them they may add identifier resources, so
// removing them can cause our resource identifiers to
diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp
index cecd95a..68db56d 100644
--- a/tools/aapt/Android.bp
+++ b/tools/aapt/Android.bp
@@ -51,6 +51,10 @@
"libz",
],
+ whole_static_libs: [
+ "libandroidfw_pathutils",
+ ],
+
cflags: [
"-Wall",
"-Werror",
diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h
index 2dc143c..dc5493f 100644
--- a/tools/aapt/CacheUpdater.h
+++ b/tools/aapt/CacheUpdater.h
@@ -7,6 +7,7 @@
#ifndef CACHE_UPDATER_H
#define CACHE_UPDATER_H
+#include <androidfw/PathUtils.h>
#include <utils/String8.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -16,6 +17,8 @@
#include <direct.h>
#endif
+#include "Utils.h"
+
using namespace android;
/** CacheUpdater
@@ -72,14 +75,14 @@
do {
// As we remove the end of existsPath add it to
// the string of paths to create.
- toCreate = existsPath.getPathLeaf().appendPath(toCreate);
- existsPath = existsPath.getPathDir();
+ toCreate = appendPathCopy(getPathLeaf(existsPath), toCreate);
+ existsPath = getPathDir(existsPath);
} while (stat(existsPath.c_str(),&s) == -1);
// Walk forwards and build directories as we go
do {
// Advance to the next segment of the path
- existsPath.appendPath(toCreate.walkPath(&remains));
+ appendPath(existsPath, walkPath(toCreate, &remains));
toCreate = remains;
#ifdef _WIN32
_mkdir(existsPath.c_str());
@@ -101,7 +104,7 @@
virtual void processImage(String8 source, String8 dest)
{
// Make sure we're trying to write to a directory that is extant
- ensureDirectoriesExist(dest.getPathDir());
+ ensureDirectoriesExist(getPathDir(dest));
preProcessImageToCache(bundle, source, dest);
};
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 60f3f27..800466a 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -12,6 +12,7 @@
#include "ResourceTable.h"
#include "XMLNode.h"
+#include <androidfw/PathUtils.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/List.h>
@@ -2486,12 +2487,12 @@
for (int i = 1; i < bundle->getFileSpecCount(); i++) {
const char* fileName = bundle->getFileSpecEntry(i);
- if (strcasecmp(String8(fileName).getPathExtension().c_str(), ".gz") == 0) {
+ if (strcasecmp(getPathExtension(String8(fileName)).c_str(), ".gz") == 0) {
printf(" '%s'... (from gzip)\n", fileName);
- result = zip->addGzip(fileName, String8(fileName).getBasePath().c_str(), NULL);
+ result = zip->addGzip(fileName, getBasePath(String8(fileName)).c_str(), NULL);
} else {
if (bundle->getJunkPath()) {
- String8 storageName = String8(fileName).getPathLeaf();
+ String8 storageName = getPathLeaf(String8(fileName));
printf(" '%s' as '%s'...\n", fileName,
ResTable::normalizeForOutput(storageName.c_str()).c_str());
result = zip->add(fileName, storageName.c_str(),
@@ -2617,10 +2618,10 @@
return original;
}
- String8 ext(original.getPathExtension());
+ String8 ext(getPathExtension(original));
if (ext == String8(".apk")) {
return String8::format("%s_%s%s",
- original.getBasePath().c_str(),
+ getBasePath(original).c_str(),
split->getDirectorySafeName().c_str(),
ext.c_str());
}
@@ -2756,7 +2757,7 @@
// generate the dependency file in the R.java package subdirectory
// e.g. gen/com/foo/app/R.java.d
dependencyFile = String8(bundle->getRClassDir());
- dependencyFile.appendPath("R.java.d");
+ appendPath(dependencyFile, "R.java.d");
}
// Make sure we have a clean dependency file to start with
fp = fopen(dependencyFile, "w");
diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp
index 1f2febe..e731ce0 100644
--- a/tools/aapt/CrunchCache.cpp
+++ b/tools/aapt/CrunchCache.cpp
@@ -5,6 +5,7 @@
// This file defines functions laid out and documented in
// CrunchCache.h
+#include <androidfw/PathUtils.h>
#include <utils/Compat.h>
#include <utils/Vector.h>
#include <utils/String8.h>
@@ -52,15 +53,15 @@
relativePath = String8(rPathPtr + offset);
if (forceOverwrite || needsUpdating(relativePath)) {
- cu->processImage(mSourcePath.appendPathCopy(relativePath),
- mDestPath.appendPathCopy(relativePath));
+ cu->processImage(appendPathCopy(mSourcePath, relativePath),
+ appendPathCopy(mDestPath, relativePath));
numFilesUpdated++;
// crunchFile(relativePath);
}
// Delete this file from the source files and (if it exists) from the
// dest files.
mSourceFiles.removeItemsAt(0);
- mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath));
+ mDestFiles.removeItem(appendPathCopy(mDestPath, relativePath));
}
// Iterate through what's left of destFiles and delete leftovers
@@ -99,7 +100,7 @@
// Retrieve modification dates for this file entry under the source and
// cache directory trees. The vectors will return a modification date of 0
// if the file doesn't exist.
- time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath));
- time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath));
+ time_t sourceDate = mSourceFiles.valueFor(appendPathCopy(mSourcePath, relativePath));
+ time_t destDate = mDestFiles.valueFor(appendPathCopy(mDestPath, relativePath));
return sourceDate > destDate;
}
diff --git a/tools/aapt/DirectoryWalker.h b/tools/aapt/DirectoryWalker.h
index cea3a6e..7f60d4d 100644
--- a/tools/aapt/DirectoryWalker.h
+++ b/tools/aapt/DirectoryWalker.h
@@ -7,6 +7,7 @@
#ifndef DIRECTORYWALKER_H
#define DIRECTORYWALKER_H
+#include <androidfw/PathUtils.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/param.h>
@@ -77,7 +78,7 @@
mEntry = *entryPtr;
// Get stats
- String8 fullPath = mBasePath.appendPathCopy(mEntry.d_name);
+ String8 fullPath = appendPathCopy(mBasePath, mEntry.d_name);
stat(fullPath.c_str(),&mStats);
return &mEntry;
};
diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp
index a5c19806..69a8fa9 100644
--- a/tools/aapt/FileFinder.cpp
+++ b/tools/aapt/FileFinder.cpp
@@ -5,6 +5,7 @@
// File Finder implementation.
// Implementation for the functions declared and documented in FileFinder.h
+#include <androidfw/PathUtils.h>
#include <utils/Vector.h>
#include <utils/String8.h>
#include <utils/KeyedVector.h>
@@ -57,7 +58,7 @@
if (entry->d_name[0] == '.') // Skip hidden files and directories
continue;
- String8 fullPath = basePath.appendPathCopy(entryName);
+ String8 fullPath = appendPathCopy(basePath, entryName);
// If this entry is a directory we'll recurse into it
if (isDirectory(fullPath.c_str()) ) {
DirectoryWalker* copy = dw->clone();
@@ -83,10 +84,10 @@
{
// Loop over the extensions, checking for a match
bool done = false;
- String8 ext(path.getPathExtension());
+ String8 ext(getPathExtension(path));
ext.toLower();
for (size_t i = 0; i < extensions.size() && !done; ++i) {
- String8 ext2 = extensions[i].getPathExtension();
+ String8 ext2 = getPathExtension(extensions[i]);
ext2.toLower();
// Compare the extensions. If a match is found, add to storage.
if (ext == ext2) {
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index c6c7e96..cd4de90 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -8,6 +8,7 @@
#include "Images.h"
+#include <androidfw/PathUtils.h>
#include <androidfw/ResourceTypes.h>
#include <utils/ByteOrder.h>
@@ -1357,7 +1358,7 @@
status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& /* assets */,
const sp<AaptFile>& file, String8* /* outNewLeafName */)
{
- String8 ext(file->getPath().getPathExtension());
+ String8 ext(getPathExtension(file->getPath()));
// We currently only process PNG images.
if (strcmp(ext.c_str(), ".png") != 0) {
@@ -1518,7 +1519,7 @@
// Check to see if we're dealing with a 9-patch
// If we are, process appropriately
- if (source.getBasePath().getPathExtension() == ".9") {
+ if (getPathExtension(getBasePath(source)) == ".9") {
if (do_9patch(source.c_str(), &imageInfo) != NO_ERROR) {
return error;
}
@@ -1584,12 +1585,12 @@
status_t postProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets,
ResourceTable* table, const sp<AaptFile>& file)
{
- String8 ext(file->getPath().getPathExtension());
+ String8 ext(getPathExtension(file->getPath()));
// At this point, now that we have all the resource data, all we need to
// do is compile XML files.
if (strcmp(ext.c_str(), ".xml") == 0) {
- String16 resourceName(parseResourceName(file->getSourceFile().getPathLeaf()));
+ String16 resourceName(parseResourceName(getPathLeaf(file->getSourceFile())));
return compileXmlFile(bundle, assets, resourceName, file, table);
}
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index a7ff5fa..5e0f87f 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -10,6 +10,7 @@
#include "ResourceFilter.h"
#include "Utils.h"
+#include <androidfw/PathUtils.h>
#include <androidfw/misc.h>
#include <utils/Log.h>
@@ -170,7 +171,7 @@
/* anything here? */
if (zip->getNumEntries() == 0) {
if (bundle->getVerbose()) {
- printf("Archive is empty -- removing %s\n", outputFile.getPathLeaf().c_str());
+ printf("Archive is empty -- removing %s\n", getPathLeaf(outputFile).c_str());
}
delete zip; // close the file so we can remove it in Win32
zip = NULL;
@@ -274,9 +275,9 @@
return true;
}
- if (strcasecmp(storageName.getPathExtension().c_str(), ".gz") == 0) {
+ if (strcasecmp(getPathExtension(storageName).c_str(), ".gz") == 0) {
fromGzip = true;
- storageName = storageName.getBasePath();
+ storageName = getBasePath(storageName);
}
if (bundle->getUpdate()) {
@@ -366,7 +367,7 @@
*/
bool okayToCompress(Bundle* bundle, const String8& pathName)
{
- String8 ext = pathName.getPathExtension();
+ String8 ext = getPathExtension(pathName);
int i;
if (ext.length() == 0)
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 4a360ed..647790b 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -19,6 +19,8 @@
#include "WorkQueue.h"
#include "XMLNode.h"
+#include <androidfw/PathUtils.h>
+
#include <algorithm>
// STATUST: mingw does seem to redefine UNKNOWN_ERROR from our enum value, so a cast is necessary.
@@ -143,8 +145,8 @@
mParams.inputFlags, mParams.navigation);
}
mPath = "res";
- mPath.appendPath(file->getGroupEntry().toDirName(mResType));
- mPath.appendPath(leaf);
+ appendPath(mPath, file->getGroupEntry().toDirName(mResType));
+ appendPath(mPath, leaf);
mBaseName = parseResourceName(leaf);
if (mBaseName == "") {
fprintf(stderr, "Error: malformed resource filename %s\n",
@@ -1686,7 +1688,7 @@
ResourceDirIterator it(fonts, String8("font"));
while ((err=it.next()) == NO_ERROR) {
// fonts can be resources other than xml.
- if (it.getFile()->getPath().getPathExtension() == ".xml") {
+ if (getPathExtension(it.getFile()->getPath()) == ".xml") {
String8 src = it.getFile()->getPrintableSource();
err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
it.getFile(), &table, xmlFlags);
@@ -1716,7 +1718,7 @@
workItem.file, &table, xmlCompilationFlags);
if (err == NO_ERROR && workItem.file->hasData()) {
- assets->addResource(workItem.resPath.getPathLeaf(),
+ assets->addResource(getPathLeaf(workItem.resPath),
workItem.resPath,
workItem.file,
workItem.file->getResourceType());
@@ -2851,7 +2853,7 @@
s++;
if (s > last && (*s == '.' || *s == 0)) {
String8 part(last, s-last);
- dest.appendPath(part);
+ appendPath(dest, part);
#ifdef _WIN32
_mkdir(dest.c_str());
#else
@@ -2861,7 +2863,7 @@
}
} while (*s);
}
- dest.appendPath(className);
+ appendPath(dest, className);
dest.append(".java");
FILE* fp = fopen(dest.c_str(), "w+");
if (fp == NULL) {
@@ -2892,7 +2894,7 @@
if (textSymbolsDest != NULL && R == className) {
String8 textDest(textSymbolsDest);
- textDest.appendPath(className);
+ appendPath(textDest, className);
textDest.append(".txt");
FILE* fp = fopen(textDest.c_str(), "w+");
@@ -2918,7 +2920,7 @@
if (bundle->getGenDependencies() && R == className) {
// Add this R.java to the dependency file
String8 dependencyFile(bundle->getRClassDir());
- dependencyFile.appendPath("R.java.d");
+ appendPath(dependencyFile, "R.java.d");
FILE *fp = fopen(dependencyFile.c_str(), "a");
fprintf(fp,"%s \\\n", dest.c_str());
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index bccf73e..421cae7 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -14,6 +14,7 @@
#include "Utils.h"
#include <algorithm>
+#include <androidfw/PathUtils.h>
#include <androidfw/ResourceTypes.h>
#include <utils/ByteOrder.h>
#include <utils/TypeHelpers.h>
@@ -83,7 +84,7 @@
sp<AaptDir> resDir = assets->getDirs().valueFor(String8("res"));
sp<AaptDir> dir = resDir->getDirs().valueFor(target->getGroupEntry().toDirName(
target->getResourceType()));
- dir->removeFile(target->getPath().getPathLeaf());
+ dir->removeFile(getPathLeaf(target->getPath()));
return NO_ERROR;
}
diff --git a/tools/aapt/Utils.cpp b/tools/aapt/Utils.cpp
index 36b018e..946916a 100644
--- a/tools/aapt/Utils.cpp
+++ b/tools/aapt/Utils.cpp
@@ -36,3 +36,26 @@
}
#endif
}
+
+String8 walkPath(const String8& path, String8* outRemains) {
+ const char* cp;
+ const char* const str = path.c_str();
+ const char* buf = str;
+
+ cp = strchr(buf, OS_PATH_SEPARATOR);
+ if (cp == buf) {
+ // don't include a leading '/'.
+ buf = buf + 1;
+ cp = strchr(buf, OS_PATH_SEPARATOR);
+ }
+
+ if (cp == nullptr) {
+ String8 res = buf != str ? String8(buf) : path;
+ if (outRemains) *outRemains = String8();
+ return res;
+ }
+
+ String8 res(buf, cp - buf);
+ if (outRemains) *outRemains = String8(cp + 1);
+ return res;
+}
diff --git a/tools/aapt/Utils.h b/tools/aapt/Utils.h
index 8eb5941..f0d6979 100644
--- a/tools/aapt/Utils.h
+++ b/tools/aapt/Utils.h
@@ -26,3 +26,13 @@
// If the default OS separator is backslash, this converts all
// backslashes to slashes, in-place. Otherwise it does nothing.
void convertToResPath(android::String8&);
+
+/**
+ * Retrieve the front (root dir) component. Optionally also return the
+ * remaining components.
+ *
+ * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c")
+ * "/tmp" --> "tmp" (remain = "")
+ * "bar.c" --> "bar.c" (remain = "")
+ */
+android::String8 walkPath(const android::String8& path, android::String8* outRemains = nullptr);