111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// Copyright 2014 The Android Open Source Project 211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// 311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// This software is licensed under the terms of the GNU General Public 411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// License version 2, as published by the Free Software Foundation, and 511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// may be copied, distributed, and modified under those terms. 611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// 711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// This program is distributed in the hope that it will be useful, 811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// but WITHOUT ANY WARRANTY; without even the implied warranty of 911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// GNU General Public License for more details. 1111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 1211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner#ifndef ANDROID_BASE_FILES_PATH_UTIL_H 1311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner#define ANDROID_BASE_FILES_PATH_UTIL_H 1411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 15d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#include "android/base/containers/StringVector.h" 16d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#include "android/base/String.h" 1711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 1811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turnernamespace android { 1911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turnernamespace base { 2011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 2111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// Utility functions to manage file paths. None of these should touch the 2211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// file system. All methods must be static. 2311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turnerclass PathUtils { 2411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turnerpublic: 2511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // An enum listing the supported host file system types. 2611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // HOST_POSIX means a Posix-like file system. 2711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // HOST_WIN32 means a Windows-like file system. 2811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // HOST_TYPE means the current host type (one of the above). 2911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // NOTE: If you update this list, modify kHostTypeCount below too. 3011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner enum HostType { 3111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner HOST_POSIX = 0, 3211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner HOST_WIN32 = 1, 3311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner#ifdef _WIN32 3411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner HOST_TYPE = HOST_WIN32, 3511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner#else 3611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner HOST_TYPE = HOST_POSIX, 3711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner#endif 3811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner }; 3911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 4011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // The number of distinct items in the HostType enumeration above. 4111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static const int kHostTypeCount = 2; 4211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 4311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Return true if |ch| is a directory separator for a given |hostType|. 4411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static bool isDirSeparator(int ch, HostType hostType); 45d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner 4611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Return true if |ch| is a directory separator for the current platform. 4711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static inline bool isDirSeparator(int ch) { 4811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner return isDirSeparator(ch, HOST_TYPE); 4911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner } 5011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 5111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Return true if |ch| is a path separator for a given |hostType|. 5211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static bool isPathSeparator(int ch, HostType hostType); 5311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 5411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Return true if |ch| is a path separator for the current platform. 5511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static inline bool isPathSeparator(int ch) { 5611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner return isPathSeparator(ch, HOST_TYPE); 5711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner } 5811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 5911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // If |path} starts with a root prefix, return its size in bytes, or 6011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // 0 otherwise. The definition of valid root prefixes depends on the 6111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // value of |hostType|. For HOST_POSIX, it's any path that begins 6211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // with a slash (/). For HOST_WIN32, the following prefixes are 6311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // recognized: 6411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // <drive>: 6511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // <drive>:<sep> 6611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // <sep><sep>volumeName<sep> 6711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static size_t rootPrefixSize(const char* path, HostType hostType); 68d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner 6911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Return the root prefix for the current platform. See above for 7011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // documentation. 7111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static inline size_t rootPrefixSize(const char* path) { 7211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner return rootPrefixSize(path, HOST_TYPE); 7311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner } 74d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner 7511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Return true iff |path| is an absolute path for a given |hostType|. 7611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static bool isAbsolute(const char* path, HostType hostType); 77d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner 7811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Return true iff |path| is an absolute path for the current host. 7911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner static inline bool isAbsolute(const char* path) { 8011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner return isAbsolute(path, HOST_TYPE); 8111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner } 8211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 8311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Decompose |path| into individual components. If |path| has a root 8411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // prefix, it will always be the first component. I.e. for Posix 8511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // systems this will be '/' (for absolute paths). For Win32 systems, 8611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // it could be 'C:" (for a path relative to a root volume) or "C:\" 8711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // for an absolute path from volume C)., 8811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // On success, return true and sets |out| to a vector of strings, 8911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // each one being a path component (prefix or subdirectory or file 9011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // name). Directory separators do not appear in components, except 9111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // for the root prefix, if any. 92d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner static StringVector decompose(const char* path, HostType hostType); 93d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner 9411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Decompose |path| into individual components for the host platform. 9511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // See comments above for more details. 96d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner static inline StringVector decompose(const char* path) { 9711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner return decompose(path, HOST_TYPE); 9811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner } 9911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 10011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Recompose a path from individual components into a file path string. 10111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // |components| is a vector of strings, and |hostType| the target 10211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // host type to use. Return a new file path string. Note that if the 10311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // first component is a root prefix, it will be kept as is, i.e.: 10411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // [ 'C:', 'foo' ] -> 'C:foo' on Win32, but not Posix where it will 10511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // be 'C:/foo'. 106d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner static String recompose(const StringVector& components, 10711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner HostType hostType); 108d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner 10911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Recompose a path from individual components into a file path string 11011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // for the current host. |components| is a vector os strings. 11111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Returns a new file path string. 112d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner static inline String recompose(const StringVector& components) { 11311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner return recompose(components, HOST_TYPE); 11411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner } 115d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner 11611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Given a list of components returned by decompose(), simplify it 11711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // by removing instances of '.' and '..' when that makes sense. 11811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // Note that it is not possible to simplify initial instances of 11911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner // '..', i.e. "foo/../../bar" -> "../bar" 120d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner static void simplifyComponents(StringVector* components); 12111823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner}; 12211823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 12311823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner// Useful shortcuts to avoid too much typing. 12411823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turnerstatic const PathUtils::HostType kHostPosix = PathUtils::HOST_POSIX; 12511823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turnerstatic const PathUtils::HostType kHostWin32 = PathUtils::HOST_WIN32; 12611823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turnerstatic const PathUtils::HostType kHostType = PathUtils::HOST_TYPE; 12711823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 12811823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner} // namespace base 12911823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner} // namespace android 13011823980b127b345cac5fdf1e2ef0a3bb6c951cbDavid 'Digit' Turner 131d3f2c27ff9f611e5047a35cb20ed53f548214fedDavid 'Digit' Turner#endif // ANDROID_BASE_FILES_PATH_UTIL_H 132