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