// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // FilePath is a container for pathnames stored in a platform's native string // type, providing containers for manipulation in according with the // platform's conventions for pathnames. It supports the following path // types: // // POSIX Windows // --------------- ---------------------------------- // Fundamental type char[] wchar_t[] // Encoding unspecified* UTF-16 // Separator / \, tolerant of / // Drive letters no case-insensitive A-Z followed by : // Alternate root // (surprise!) \\ (2 Separators), for UNC paths // // * The encoding need not be specified on POSIX systems, although some // POSIX-compliant systems do specify an encoding. Mac OS X uses UTF-8. // Chrome OS also uses UTF-8. // Linux does not specify an encoding, but in practice, the locale's // character set may be used. // // For more arcane bits of path trivia, see below. // // FilePath objects are intended to be used anywhere paths are. An // application may pass FilePath objects around internally, masking the // underlying differences between systems, only differing in implementation // where interfacing directly with the system. For example, a single // OpenFile(const FilePath &) function may be made available, allowing all // callers to operate without regard to the underlying implementation. On // POSIX-like platforms, OpenFile might wrap fopen, and on Windows, it might // wrap _wfopen_s, perhaps both by calling file_path.value().c_str(). This // allows each platform to pass pathnames around without requiring conversions // between encodings, which has an impact on performance, but more imporantly, // has an impact on correctness on platforms that do not have well-defined // encodings for pathnames. // // Several methods are available to perform common operations on a FilePath // object, such as determining the parent directory (DirName), isolating the // final path component (BaseName), and appending a relative pathname string // to an existing FilePath object (Append). These methods are highly // recommended over attempting to split and concatenate strings directly. // These methods are based purely on string manipulation and knowledge of // platform-specific pathname conventions, and do not consult the filesystem // at all, making them safe to use without fear of blocking on I/O operations. // These methods do not function as mutators but instead return distinct // instances of FilePath objects, and are therefore safe to use on const // objects. The objects themselves are safe to share between threads. // // To aid in initialization of FilePath objects from string literals, a // FILE_PATH_LITERAL macro is provided, which accounts for the difference // between char[]-based pathnames on POSIX systems and wchar_t[]-based // pathnames on Windows. // // As a precaution against premature truncation, paths can't contain NULs. // // Because a FilePath object should not be instantiated at the global scope, // instead, use a FilePath::CharType[] and initialize it with // FILE_PATH_LITERAL. At runtime, a FilePath object can be created from the // character array. Example: // // | const FilePath::CharType kLogFileName[] = FILE_PATH_LITERAL("log.txt"); // | // | void Function() { // | FilePath log_file_path(kLogFileName); // | [...] // | } // // WARNING: FilePaths should ALWAYS be displayed with LTR directionality, even // when the UI language is RTL. This means you always need to pass filepaths // through base::i18n::WrapPathWithLTRFormatting() before displaying it in the // RTL UI. // // This is a very common source of bugs, please try to keep this in mind. // // ARCANE BITS OF PATH TRIVIA // // - A double leading slash is actually part of the POSIX standard. Systems // are allowed to treat // as an alternate root, as Windows does for UNC // (network share) paths. Most POSIX systems don't do anything special // with two leading slashes, but FilePath handles this case properly // in case it ever comes across such a system. FilePath needs this support // for Windows UNC paths, anyway. // References: // The Open Group Base Specifications Issue 7, sections 3.267 ("Pathname") // and 4.12 ("Pathname Resolution"), available at: // http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_267 // http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12 // // - Windows treats c:\\ the same way it treats \\. This was intended to // allow older applications that require drive letters to support UNC paths // like \\server\share\path, by permitting c:\\server\share\path as an // equivalent. Since the OS treats these paths specially, FilePath needs // to do the same. Since Windows can use either / or \ as the separator, // FilePath treats c://, c:\\, //, and \\ all equivalently. // Reference: // The Old New Thing, "Why is a drive letter permitted in front of UNC // paths (sometimes)?", available at: // http://blogs.msdn.com/oldnewthing/archive/2005/11/22/495740.aspx #ifndef BASE_FILES_FILE_PATH_H_ #define BASE_FILES_FILE_PATH_H_ #include <cstddef> #include <iosfwd> #include <string> #include <string_view> #include <vector> #include "base/base_export.h" #include "base/trace_event/base_tracing_forward.h" #include "build/build_config.h" // Windows-style drive letter support and pathname separator characters can be // enabled and disabled independently, to aid testing. These #defines are // here so that the same setting can be used in both the implementation and // in the unit test. #if BUILDFLAG(IS_WIN) #define FILE_PATH_USES_DRIVE_LETTERS #define FILE_PATH_USES_WIN_SEPARATORS #endif // BUILDFLAG(IS_WIN) // To print path names portably use PRFilePath (based on PRIuS and friends from // C99 and format_macros.h) like this: // base::StringPrintf("Path is %" PRFilePath ".\n", path.value().c_str()); #if BUILDFLAG(IS_WIN) #define PRFilePath … #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #define PRFilePath … #endif // BUILDFLAG(IS_WIN) // Macros for string literal initialization of FilePath::CharType[]. #if BUILDFLAG(IS_WIN) // The `FILE_PATH_LITERAL_INTERNAL` indirection allows `FILE_PATH_LITERAL` to // work correctly with macro parameters, for example // `FILE_PATH_LITERAL(TEST_FILE)` where `TEST_FILE` is a macro #defined as // "TestFile". #define FILE_PATH_LITERAL_INTERNAL … #define FILE_PATH_LITERAL … #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #define FILE_PATH_LITERAL(x) … #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_APPLE) typedef const struct __CFString* CFStringRef; #endif namespace base { class SafeBaseName; class Pickle; class PickleIterator; // An abstraction to isolate users from the differences between native // pathnames on different platforms. class BASE_EXPORT FilePath { … }; BASE_EXPORT std::ostream& operator<<(std::ostream& out, const FilePath& file_path); } // namespace base namespace std { template <> struct hash<base::FilePath> { … }; } // namespace std #endif // BASE_FILES_FILE_PATH_H_