|  | /* | 
|  | *  Copyright 2004 The WebRTC Project Authors. All rights reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #if defined(WEBRTC_WIN) | 
|  | #include <windows.h> | 
|  | #include <shellapi.h> | 
|  | #include <shlobj.h> | 
|  | #include <tchar.h> | 
|  | #endif  // WEBRTC_WIN | 
|  |  | 
|  | #include "rtc_base/checks.h" | 
|  | #include "rtc_base/logging.h" | 
|  | #include "rtc_base/pathutils.h" | 
|  | #include "rtc_base/stringutils.h" | 
|  |  | 
|  | namespace rtc { | 
|  |  | 
|  | static const char EMPTY_STR[] = ""; | 
|  |  | 
|  | // EXT_DELIM separates a file basename from extension | 
|  | const char EXT_DELIM = '.'; | 
|  |  | 
|  | // FOLDER_DELIMS separate folder segments and the filename | 
|  | const char* const FOLDER_DELIMS = "/\\"; | 
|  |  | 
|  | // DEFAULT_FOLDER_DELIM is the preferred delimiter for this platform | 
|  | #ifdef WEBRTC_WIN | 
|  | const char DEFAULT_FOLDER_DELIM = '\\'; | 
|  | #else  // !WEBRTC_WIN | 
|  | const char DEFAULT_FOLDER_DELIM = '/'; | 
|  | #endif  // !WEBRTC_WIN | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // Pathname - parsing of pathnames into components, and vice versa | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | bool Pathname::IsFolderDelimiter(char ch) { | 
|  | return (nullptr != ::strchr(FOLDER_DELIMS, ch)); | 
|  | } | 
|  |  | 
|  | char Pathname::DefaultFolderDelimiter() { | 
|  | return DEFAULT_FOLDER_DELIM; | 
|  | } | 
|  |  | 
|  | Pathname::Pathname() | 
|  | : folder_delimiter_(DEFAULT_FOLDER_DELIM) { | 
|  | } | 
|  |  | 
|  | Pathname::Pathname(const Pathname&) = default; | 
|  | Pathname::Pathname(Pathname&&) = default; | 
|  |  | 
|  | Pathname::Pathname(const std::string& pathname) | 
|  | : folder_delimiter_(DEFAULT_FOLDER_DELIM) { | 
|  | SetPathname(pathname); | 
|  | } | 
|  |  | 
|  | Pathname::Pathname(const std::string& folder, const std::string& filename) | 
|  | : folder_delimiter_(DEFAULT_FOLDER_DELIM) { | 
|  | SetPathname(folder, filename); | 
|  | } | 
|  |  | 
|  | Pathname& Pathname::operator=(const Pathname&) = default; | 
|  | Pathname& Pathname::operator=(Pathname&&) = default; | 
|  |  | 
|  | std::string Pathname::pathname() const { | 
|  | std::string pathname(folder_); | 
|  | pathname.append(basename_); | 
|  | pathname.append(extension_); | 
|  | if (pathname.empty()) { | 
|  | // Instead of the empty pathname, return the current working directory. | 
|  | pathname.push_back('.'); | 
|  | pathname.push_back(folder_delimiter_); | 
|  | } | 
|  | return pathname; | 
|  | } | 
|  |  | 
|  | void Pathname::SetPathname(const std::string& pathname) { | 
|  | std::string::size_type pos = pathname.find_last_of(FOLDER_DELIMS); | 
|  | if (pos != std::string::npos) { | 
|  | SetFolder(pathname.substr(0, pos + 1)); | 
|  | SetFilename(pathname.substr(pos + 1)); | 
|  | } else { | 
|  | SetFolder(EMPTY_STR); | 
|  | SetFilename(pathname); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Pathname::SetPathname(const std::string& folder, | 
|  | const std::string& filename) { | 
|  | SetFolder(folder); | 
|  | SetFilename(filename); | 
|  | } | 
|  |  | 
|  | void Pathname::SetFolder(const std::string& folder) { | 
|  | folder_.assign(folder); | 
|  | // Ensure folder ends in a path delimiter | 
|  | if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) { | 
|  | folder_.push_back(folder_delimiter_); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Pathname::AppendFolder(const std::string& folder) { | 
|  | folder_.append(folder); | 
|  | // Ensure folder ends in a path delimiter | 
|  | if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) { | 
|  | folder_.push_back(folder_delimiter_); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool Pathname::SetBasename(const std::string& basename) { | 
|  | if(basename.find_first_of(FOLDER_DELIMS) != std::string::npos) { | 
|  | return false; | 
|  | } | 
|  | basename_.assign(basename); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool Pathname::SetExtension(const std::string& extension) { | 
|  | if (extension.find_first_of(FOLDER_DELIMS) != std::string::npos || | 
|  | extension.find_first_of(EXT_DELIM, 1) != std::string::npos) { | 
|  | return false; | 
|  | } | 
|  | extension_.assign(extension); | 
|  | // Ensure extension begins with the extension delimiter | 
|  | if (!extension_.empty() && (extension_[0] != EXT_DELIM)) { | 
|  | extension_.insert(extension_.begin(), EXT_DELIM); | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | std::string Pathname::filename() const { | 
|  | std::string filename(basename_); | 
|  | filename.append(extension_); | 
|  | return filename; | 
|  | } | 
|  |  | 
|  | bool Pathname::SetFilename(const std::string& filename) { | 
|  | std::string::size_type pos = filename.rfind(EXT_DELIM); | 
|  | if ((pos == std::string::npos) || (pos == 0)) { | 
|  | return SetExtension(EMPTY_STR) && SetBasename(filename); | 
|  | } else { | 
|  | return SetExtension(filename.substr(pos)) && SetBasename(filename.substr(0, pos)); | 
|  | } | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | } // namespace rtc |