diff --git a/modules/audio_processing/test/conversational_speech/BUILD.gn b/modules/audio_processing/test/conversational_speech/BUILD.gn index 721ebc7ee5..551781b8bc 100644 --- a/modules/audio_processing/test/conversational_speech/BUILD.gn +++ b/modules/audio_processing/test/conversational_speech/BUILD.gn @@ -51,6 +51,7 @@ rtc_static_library("lib") { "../../../../common_audio", "../../../../rtc_base:checks", "../../../../rtc_base:rtc_base_approved", + "../../../../test:fileutils", "//third_party/abseil-cpp/absl/memory", ] visibility = [ ":*" ] # Only targets in this file can depend on this. diff --git a/modules/audio_processing/test/conversational_speech/mock_wavreader_factory.cc b/modules/audio_processing/test/conversational_speech/mock_wavreader_factory.cc index eb8e3bed3c..a45e3bbfa7 100644 --- a/modules/audio_processing/test/conversational_speech/mock_wavreader_factory.cc +++ b/modules/audio_processing/test/conversational_speech/mock_wavreader_factory.cc @@ -12,7 +12,6 @@ #include "modules/audio_processing/test/conversational_speech/mock_wavreader.h" #include "rtc_base/logging.h" -#include "rtc_base/pathutils.h" #include "test/gmock.h" namespace webrtc { @@ -39,9 +38,10 @@ MockWavReaderFactory::~MockWavReaderFactory() = default; std::unique_ptr MockWavReaderFactory::CreateMock( const std::string& filepath) { // Search the parameters corresponding to filepath. - const rtc::Pathname audiotrack_file_path(filepath); - const auto it = - audiotrack_names_params_.find(audiotrack_file_path.filename()); + size_t delimiter = filepath.find_last_of("/\\"); // Either windows or posix + std::string filename = + filepath.substr(delimiter == std::string::npos ? 0 : delimiter + 1); + const auto it = audiotrack_names_params_.find(filename); // If not found, use default parameters. if (it == audiotrack_names_params_.end()) { diff --git a/modules/audio_processing/test/conversational_speech/multiend_call.cc b/modules/audio_processing/test/conversational_speech/multiend_call.cc index d633d90e9c..4e2f54d150 100644 --- a/modules/audio_processing/test/conversational_speech/multiend_call.cc +++ b/modules/audio_processing/test/conversational_speech/multiend_call.cc @@ -14,7 +14,7 @@ #include #include "rtc_base/logging.h" -#include "rtc_base/pathutils.h" +#include "test/testsupport/fileutils.h" namespace webrtc { namespace test { @@ -50,13 +50,13 @@ bool MultiEndCall::CreateAudioTrackReaders() { if (it != audiotrack_readers_.end()) continue; - // Instance Pathname to retrieve the full path to the audiotrack file. - const rtc::Pathname audiotrack_file_path(audiotracks_path_, - turn.audiotrack_file_name); + const std::string audiotrack_file_path = + test::JoinFilename(audiotracks_path_, turn.audiotrack_file_name); // Map the audiotrack file name to a new instance of WavReaderInterface. std::unique_ptr wavreader = - wavreader_abstract_factory_->Create(audiotrack_file_path.pathname()); + wavreader_abstract_factory_->Create( + test::JoinFilename(audiotracks_path_, turn.audiotrack_file_name)); if (sample_rate_hz_ == 0) { sample_rate_hz_ = wavreader->SampleRate(); diff --git a/modules/audio_processing/test/conversational_speech/simulator.cc b/modules/audio_processing/test/conversational_speech/simulator.cc index c2fb7808e0..c400499fd3 100644 --- a/modules/audio_processing/test/conversational_speech/simulator.cc +++ b/modules/audio_processing/test/conversational_speech/simulator.cc @@ -25,7 +25,7 @@ #include "rtc_base/constructormagic.h" #include "rtc_base/logging.h" #include "rtc_base/numerics/safe_conversions.h" -#include "rtc_base/pathutils.h" +#include "test/testsupport/fileutils.h" namespace webrtc { namespace test { @@ -46,21 +46,20 @@ InitSpeakerOutputFilePaths(const std::set& speaker_names, // Add near-end and far-end output paths into the map. for (const auto& speaker_name : speaker_names) { - const rtc::Pathname near_end_path(output_path, - "s_" + speaker_name + "-near_end.wav"); + const std::string near_end_path = + test::JoinFilename(output_path, "s_" + speaker_name + "-near_end.wav"); RTC_LOG(LS_VERBOSE) << "The near-end audio track will be created in " - << near_end_path.pathname() << "."; + << near_end_path << "."; - const rtc::Pathname far_end_path(output_path, - "s_" + speaker_name + "-far_end.wav"); + const std::string far_end_path = + test::JoinFilename(output_path, "s_" + speaker_name + "-far_end.wav"); RTC_LOG(LS_VERBOSE) << "The far-end audio track will be created in " - << far_end_path.pathname() << "."; + << far_end_path << "."; // Add to map. speaker_output_file_paths_map->emplace( std::piecewise_construct, std::forward_as_tuple(speaker_name), - std::forward_as_tuple(near_end_path.pathname(), - far_end_path.pathname())); + std::forward_as_tuple(near_end_path, far_end_path)); } return speaker_output_file_paths_map; diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 7f05dc4cc6..076834d10a 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -121,8 +121,6 @@ rtc_source_set("rtc_base_approved") { "numerics/sample_counter.cc", "numerics/sample_counter.h", "onetimeevent.h", - "pathutils.cc", - "pathutils.h", "platform_file.cc", "platform_file.h", "race_checker.cc", @@ -1108,7 +1106,6 @@ if (rtc_include_tests) { "numerics/safe_minmax_unittest.cc", "numerics/sample_counter_unittest.cc", "onetimeevent_unittest.cc", - "pathutils_unittest.cc", "platform_file_unittest.cc", "platform_thread_unittest.cc", "random_unittest.cc", diff --git a/rtc_base/filerotatingstream.cc b/rtc_base/filerotatingstream.cc index c28616d8f6..e9ac394244 100644 --- a/rtc_base/filerotatingstream.cc +++ b/rtc_base/filerotatingstream.cc @@ -15,16 +15,65 @@ #include #include +#if defined(WEBRTC_WIN) +#include +#include "rtc_base/stringutils.h" +#else +#include +#endif // WEBRTC_WIN + +#include "absl/strings/match.h" #include "rtc_base/checks.h" #include "rtc_base/fileutils.h" #include "rtc_base/logging.h" -#include "rtc_base/pathutils.h" // Note: We use fprintf for logging in the write paths of this stream to avoid // infinite loops when logging. namespace rtc { +namespace { + +std::string AddTrailingPathDelimiterIfNeeded(std::string directory); +bool IsFolder(const std::string& file); + +#if defined(WEBRTC_WIN) + +std::string AddTrailingPathDelimiterIfNeeded(std::string directory) { + if (absl::EndsWith(directory, "\\")) { + return directory; + } + return directory + "\\"; +} + +bool IsFolder(const std::string& file) { + WIN32_FILE_ATTRIBUTE_DATA data = {0}; + if (0 == ::GetFileAttributesEx(ToUtf16(file).c_str(), GetFileExInfoStandard, + &data)) + return false; + return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == + FILE_ATTRIBUTE_DIRECTORY; +} + +#else // defined(WEBRTC_WIN) + +std::string AddTrailingPathDelimiterIfNeeded(std::string directory) { + if (absl::EndsWith(directory, "/")) { + return directory; + } + return directory + "/"; +} + +bool IsFolder(const std::string& file) { + struct stat st; + int res = ::stat(file.c_str(), &st); + return res == 0 && S_ISDIR(st.st_mode); +} + +#endif + +} // namespace + FileRotatingStream::FileRotatingStream(const std::string& dir_path, const std::string& file_prefix) : FileRotatingStream(dir_path, file_prefix, 0, 0, kRead) {} @@ -47,7 +96,7 @@ FileRotatingStream::FileRotatingStream(const std::string& dir_path, size_t max_file_size, size_t num_files, Mode mode) - : dir_path_(dir_path), + : dir_path_(AddTrailingPathDelimiterIfNeeded(dir_path)), file_prefix_(file_prefix), mode_(mode), file_stream_(nullptr), @@ -56,7 +105,7 @@ FileRotatingStream::FileRotatingStream(const std::string& dir_path, rotation_index_(0), current_bytes_written_(0), disable_buffering_(false) { - RTC_DCHECK(Filesystem::IsFolder(dir_path)); + RTC_DCHECK(IsFolder(dir_path)); switch (mode) { case kWrite: { file_names_.clear(); @@ -188,7 +237,6 @@ bool FileRotatingStream::GetSize(size_t* size) const { *size = 0; size_t total_size = 0; for (auto file_name : file_names_) { - Pathname pathname(file_name); size_t file_size = 0; if (Filesystem::GetFileSize(file_name, &file_size)) { total_size += file_size; @@ -307,17 +355,14 @@ std::vector FileRotatingStream::GetFilesWithPrefix() const { std::vector files; // Iterate over the files in the directory. DirectoryIterator it; - Pathname dir_path; - dir_path.SetFolder(dir_path_); - if (!it.Iterate(dir_path)) { + if (!it.Iterate(dir_path_)) { return files; } do { std::string current_name = it.Name(); if (current_name.size() && !it.IsDirectory() && current_name.compare(0, file_prefix_.size(), file_prefix_) == 0) { - Pathname path(dir_path_, current_name); - files.push_back(path.pathname()); + files.push_back(it.PathName()); } } while (it.Next()); return files; @@ -334,8 +379,7 @@ std::string FileRotatingStream::GetFilePath(size_t index, RTC_DCHECK_LT(1 + max_digits, buffer_size); std::snprintf(file_postfix, buffer_size, "_%0*zu", max_digits, index); - Pathname file_path(dir_path_, file_prefix_ + file_postfix); - return file_path.pathname(); + return dir_path_ + file_prefix_ + file_postfix; } CallSessionFileRotatingStream::CallSessionFileRotatingStream( diff --git a/rtc_base/filerotatingstream_unittest.cc b/rtc_base/filerotatingstream_unittest.cc index 19055162fd..7ca7e3ecc7 100644 --- a/rtc_base/filerotatingstream_unittest.cc +++ b/rtc_base/filerotatingstream_unittest.cc @@ -15,7 +15,6 @@ #include "rtc_base/filerotatingstream.h" #include "rtc_base/fileutils.h" #include "rtc_base/gunit.h" -#include "rtc_base/pathutils.h" #include "test/testsupport/fileutils.h" namespace rtc { @@ -46,12 +45,15 @@ class MAYBE_FileRotatingStreamTest : public ::testing::Test { void Init(const std::string& dir_name, const std::string& file_prefix, size_t max_file_size, - size_t num_log_files) { + size_t num_log_files, + bool ensure_trailing_delimiter = true) { dir_path_ = webrtc::test::OutputPath(); // Append per-test output path in order to run within gtest parallel. dir_path_.append(dir_name); - dir_path_.push_back(Pathname::DefaultFolderDelimiter()); + if (ensure_trailing_delimiter) { + dir_path_.append(webrtc::test::kPathDelimiter); + } ASSERT_TRUE(webrtc::test::CreateDir(dir_path_)); stream_.reset(new FileRotatingStream(dir_path_, file_prefix, max_file_size, num_log_files)); @@ -174,6 +176,53 @@ TEST_F(MAYBE_FileRotatingStreamTest, WriteAndRead) { dir_path_, kFilePrefix); } +// Tests that a write operation (with dir name without delimiter) followed by a +// read returns the expected data and writes to the expected files. +TEST_F(MAYBE_FileRotatingStreamTest, WriteWithoutDelimiterAndRead) { + Init("FileRotatingStreamTestWriteWithoutDelimiterAndRead", kFilePrefix, + kMaxFileSize, 3, + /* ensure_trailing_delimiter*/ false); + + ASSERT_TRUE(stream_->Open()); + // The test is set up to create three log files of length 2. Write and check + // contents. + std::string messages[3] = {"aa", "bb", "cc"}; + for (size_t i = 0; i < arraysize(messages); ++i) { + const std::string& message = messages[i]; + WriteAndFlush(message.c_str(), message.size()); + } + std::string message("d"); + WriteAndFlush(message.c_str(), message.size()); + + // Reopen for read. + std::string expected_contents("bbccd"); + VerifyStreamRead(expected_contents.c_str(), expected_contents.size(), + dir_path_ + webrtc::test::kPathDelimiter, kFilePrefix); +} + +// Tests that a write operation followed by a read (without trailing delimiter) +// returns the expected data and writes to the expected files. +TEST_F(MAYBE_FileRotatingStreamTest, WriteAndReadWithoutDelimiter) { + Init("FileRotatingStreamTestWriteAndReadWithoutDelimiter", kFilePrefix, + kMaxFileSize, 3); + + ASSERT_TRUE(stream_->Open()); + // The test is set up to create three log files of length 2. Write and check + // contents. + std::string messages[3] = {"aa", "bb", "cc"}; + for (size_t i = 0; i < arraysize(messages); ++i) { + const std::string& message = messages[i]; + WriteAndFlush(message.c_str(), message.size()); + } + std::string message("d"); + WriteAndFlush(message.c_str(), message.size()); + + // Reopen for read. + std::string expected_contents("bbccd"); + VerifyStreamRead(expected_contents.c_str(), expected_contents.size(), + dir_path_.substr(0, dir_path_.size() - 1), kFilePrefix); +} + // Tests that writing data greater than the total capacity of the files // overwrites the files correctly and is read correctly after. TEST_F(MAYBE_FileRotatingStreamTest, WriteOverflowAndRead) { @@ -218,7 +267,7 @@ class MAYBE_CallSessionFileRotatingStreamTest : public ::testing::Test { // Append per-test output path in order to run within gtest parallel. dir_path_.append(dir_name); - dir_path_.push_back(Pathname::DefaultFolderDelimiter()); + dir_path_.append(webrtc::test::kPathDelimiter); ASSERT_TRUE(webrtc::test::CreateDir(dir_path_)); stream_.reset( new CallSessionFileRotatingStream(dir_path_, max_total_log_size)); diff --git a/rtc_base/fileutils.cc b/rtc_base/fileutils.cc index 0adbbac4b0..1086f3c7f7 100644 --- a/rtc_base/fileutils.cc +++ b/rtc_base/fileutils.cc @@ -11,7 +11,6 @@ #include "rtc_base/fileutils.h" #include "rtc_base/checks.h" -#include "rtc_base/pathutils.h" #if defined(WEBRTC_WIN) #include "rtc_base/stringutils.h" // for ToUtf16 @@ -58,12 +57,12 @@ DirectoryIterator::~DirectoryIterator() { // Starts traversing a directory. // dir is the directory to traverse // returns true if the directory exists and is valid -bool DirectoryIterator::Iterate(const Pathname& dir) { - directory_ = dir.pathname(); +bool DirectoryIterator::Iterate(const std::string& dir) { + directory_ = dir; #if defined(WEBRTC_WIN) if (handle_ != INVALID_HANDLE_VALUE) ::FindClose(handle_); - std::string d = dir.pathname() + '*'; + std::string d = dir + '*'; handle_ = ::FindFirstFile(ToUtf16(d).c_str(), &data_); if (handle_ == INVALID_HANDLE_VALUE) return false; @@ -77,7 +76,7 @@ bool DirectoryIterator::Iterate(const Pathname& dir) { if (dirent_ == nullptr) return false; - if (::stat(std::string(directory_ + Name()).c_str(), &stat_) != 0) + if (::stat(PathName().c_str(), &stat_) != 0) return false; #endif return true; @@ -93,7 +92,7 @@ bool DirectoryIterator::Next() { if (dirent_ == nullptr) return false; - return ::stat(std::string(directory_ + Name()).c_str(), &stat_) == 0; + return ::stat(PathName().c_str(), &stat_) == 0; #endif } @@ -112,7 +111,17 @@ std::string DirectoryIterator::Name() const { return ToUtf8(data_.cFileName); #else RTC_DCHECK(dirent_); - return dirent_->d_name; + return std::string(dirent_->d_name); +#endif +} + +// returns the name of the file currently pointed to +std::string DirectoryIterator::PathName() const { +#if defined(WEBRTC_WIN) + return directory_ + "\\" + ToUtf8(data_.cFileName); +#else + RTC_DCHECK(dirent_); + return directory_ + "/" + dirent_->d_name; #endif } diff --git a/rtc_base/fileutils.h b/rtc_base/fileutils.h index deaf2e387a..d85b6b1787 100644 --- a/rtc_base/fileutils.h +++ b/rtc_base/fileutils.h @@ -25,8 +25,6 @@ namespace rtc { -class Pathname; - ////////////////////////// // Directory Iterator // ////////////////////////// @@ -44,22 +42,25 @@ class DirectoryIterator { // Destructor virtual ~DirectoryIterator(); - // Starts traversing a directory - // dir is the directory to traverse - // returns true if the directory exists and is valid - // The iterator will point to the first entry in the directory - virtual bool Iterate(const Pathname& path); + // Starts traversing a directory. + // |dir| is the directory to traverse. + // returns true if the directory exists and is valid. + // The iterator will point to the first entry in the directory. + virtual bool Iterate(const std::string& dir); // Advances to the next file // returns true if there were more files in the directory. virtual bool Next(); - // returns true if the file currently pointed to is a directory + // Returns true if the file currently pointed to is a directory. virtual bool IsDirectory() const; - // returns the name of the file currently pointed to + // Returns the name of the file currently pointed to. virtual std::string Name() const; + // Returns complete name of the file, including directory part. + virtual std::string PathName() const; + private: std::string directory_; #if defined(WEBRTC_WIN) @@ -79,42 +80,37 @@ class FilesystemInterface { // This will attempt to delete the path located at filename. // It DCHECKs and returns false if the path points to a folder or a // non-existent file. - virtual bool DeleteFile(const Pathname& filename) = 0; + virtual bool DeleteFile(const std::string& filename) = 0; // This moves a file from old_path to new_path, where "old_path" is a // plain file. This DCHECKs and returns false if old_path points to a // directory, and returns true if the function succeeds. - virtual bool MoveFile(const Pathname& old_path, const Pathname& new_path) = 0; - - // Returns true if pathname refers to a directory - virtual bool IsFolder(const Pathname& pathname) = 0; + virtual bool MoveFile(const std::string& old_path, + const std::string& new_path) = 0; // Returns true if pathname refers to a file - virtual bool IsFile(const Pathname& pathname) = 0; + virtual bool IsFile(const std::string& pathname) = 0; // Determines the size of the file indicated by path. - virtual bool GetFileSize(const Pathname& path, size_t* size) = 0; + virtual bool GetFileSize(const std::string& path, size_t* size) = 0; }; class Filesystem { public: - static bool DeleteFile(const Pathname& filename) { + static bool DeleteFile(const std::string& filename) { return GetFilesystem()->DeleteFile(filename); } - static bool MoveFile(const Pathname& old_path, const Pathname& new_path) { + static bool MoveFile(const std::string& old_path, + const std::string& new_path) { return GetFilesystem()->MoveFile(old_path, new_path); } - static bool IsFolder(const Pathname& pathname) { - return GetFilesystem()->IsFolder(pathname); - } - - static bool IsFile(const Pathname& pathname) { + static bool IsFile(const std::string& pathname) { return GetFilesystem()->IsFile(pathname); } - static bool GetFileSize(const Pathname& path, size_t* size) { + static bool GetFileSize(const std::string& path, size_t* size) { return GetFilesystem()->GetFileSize(path, size); } diff --git a/rtc_base/pathutils.cc b/rtc_base/pathutils.cc deleted file mode 100644 index 07646716c2..0000000000 --- a/rtc_base/pathutils.cc +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 -#include -#include -#include -#endif // WEBRTC_WIN - -#include // for strchr - -#include "rtc_base/pathutils.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 diff --git a/rtc_base/pathutils.h b/rtc_base/pathutils.h deleted file mode 100644 index 59f2a4ac29..0000000000 --- a/rtc_base/pathutils.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ - -#ifndef RTC_BASE_PATHUTILS_H_ -#define RTC_BASE_PATHUTILS_H_ - -#include - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// Pathname - parsing of pathnames into components, and vice versa. -// -// To establish consistent terminology, a filename never contains a folder -// component. A folder never contains a filename. A pathname may include -// a folder and/or filename component. Here are some examples: -// -// pathname() /home/john/example.txt -// folder() /home/john/ -// filename() example.txt -// parent_folder() /home/ -// folder_name() john/ -// basename() example -// extension() .txt -// -// Basename may begin, end, and/or include periods, but no folder delimiters. -// If extension exists, it consists of a period followed by zero or more -// non-period/non-delimiter characters, and basename is non-empty. -/////////////////////////////////////////////////////////////////////////////// - -class Pathname { - public: - // Folder delimiters are slash and backslash - static bool IsFolderDelimiter(char ch); - static char DefaultFolderDelimiter(); - - Pathname(); - Pathname(const Pathname&); - Pathname(Pathname&&); - Pathname(const std::string& pathname); - Pathname(const std::string& folder, const std::string& filename); - - Pathname& operator=(const Pathname&); - Pathname& operator=(Pathname&&); - - // Returns the folder and filename components. If the pathname is empty, - // returns a string representing the current directory (as a relative path, - // i.e., "."). - std::string pathname() const; - void SetPathname(const std::string& pathname); - void SetPathname(const std::string& folder, const std::string& filename); - - // SetFolder and AppendFolder will append a folder delimiter, if needed. - void SetFolder(const std::string& folder); - void AppendFolder(const std::string& folder); - - bool SetBasename(const std::string& basename); - - // SetExtension will prefix a period, if needed. - bool SetExtension(const std::string& extension); - - std::string filename() const; - bool SetFilename(const std::string& filename); - - private: - std::string folder_, basename_, extension_; - char folder_delimiter_; -}; - -} // namespace rtc - -#endif // RTC_BASE_PATHUTILS_H_ diff --git a/rtc_base/pathutils_unittest.cc b/rtc_base/pathutils_unittest.cc deleted file mode 100644 index fae4f0aba5..0000000000 --- a/rtc_base/pathutils_unittest.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2007 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. - */ - -#include "rtc_base/pathutils.h" -#include "rtc_base/gunit.h" - -TEST(Pathname, ReturnsDotForEmptyPathname) { - const std::string kCWD = - std::string(".") + rtc::Pathname::DefaultFolderDelimiter(); - - rtc::Pathname path("/", ""); - EXPECT_TRUE (path.filename().empty()); - EXPECT_FALSE(path.pathname().empty()); - EXPECT_EQ(std::string("/"), path.pathname()); - - path.SetPathname("", "foo"); - EXPECT_FALSE(path.filename().empty()); - EXPECT_FALSE(path.pathname().empty()); - EXPECT_EQ(std::string("foo"), path.pathname()); - - path.SetPathname("", ""); - EXPECT_TRUE (path.filename().empty()); - EXPECT_FALSE(path.pathname().empty()); - EXPECT_EQ(kCWD, path.pathname()); - - path.SetPathname(kCWD, ""); - EXPECT_TRUE (path.filename().empty()); - EXPECT_FALSE(path.pathname().empty()); - EXPECT_EQ(kCWD, path.pathname()); -} diff --git a/rtc_base/unixfilesystem.cc b/rtc_base/unixfilesystem.cc index 2a941e2b74..ee9e3f069a 100644 --- a/rtc_base/unixfilesystem.cc +++ b/rtc_base/unixfilesystem.cc @@ -38,7 +38,6 @@ #include "rtc_base/checks.h" #include "rtc_base/logging.h" -#include "rtc_base/pathutils.h" namespace rtc { @@ -46,47 +45,39 @@ UnixFilesystem::UnixFilesystem() {} UnixFilesystem::~UnixFilesystem() {} -bool UnixFilesystem::DeleteFile(const Pathname& filename) { - RTC_LOG(LS_INFO) << "Deleting file:" << filename.pathname(); +bool UnixFilesystem::DeleteFile(const std::string& filename) { + RTC_LOG(LS_INFO) << "Deleting file:" << filename; if (!IsFile(filename)) { RTC_DCHECK(IsFile(filename)); return false; } - return ::unlink(filename.pathname().c_str()) == 0; + return ::unlink(filename.c_str()) == 0; } -bool UnixFilesystem::MoveFile(const Pathname& old_path, - const Pathname& new_path) { +bool UnixFilesystem::MoveFile(const std::string& old_path, + const std::string& new_path) { if (!IsFile(old_path)) { RTC_DCHECK(IsFile(old_path)); return false; } - RTC_LOG(LS_VERBOSE) << "Moving " << old_path.pathname() << " to " - << new_path.pathname(); - if (rename(old_path.pathname().c_str(), new_path.pathname().c_str()) != 0) { + RTC_LOG(LS_VERBOSE) << "Moving " << old_path << " to " << new_path; + if (rename(old_path.c_str(), new_path.c_str()) != 0) { return false; } return true; } -bool UnixFilesystem::IsFolder(const Pathname& path) { +bool UnixFilesystem::IsFile(const std::string& pathname) { struct stat st; - if (stat(path.pathname().c_str(), &st) < 0) - return false; - return S_ISDIR(st.st_mode); -} - -bool UnixFilesystem::IsFile(const Pathname& pathname) { - struct stat st; - int res = ::stat(pathname.pathname().c_str(), &st); + int res = ::stat(pathname.c_str(), &st); // Treat symlinks, named pipes, etc. all as files. return res == 0 && !S_ISDIR(st.st_mode); } -bool UnixFilesystem::GetFileSize(const Pathname& pathname, size_t* size) { +bool UnixFilesystem::GetFileSize(const std::string& pathname, size_t* size) { struct stat st; - if (::stat(pathname.pathname().c_str(), &st) != 0) + if (::stat(pathname.c_str(), &st) != 0) return false; *size = st.st_size; return true; diff --git a/rtc_base/unixfilesystem.h b/rtc_base/unixfilesystem.h index d95132c0a5..32af9b510a 100644 --- a/rtc_base/unixfilesystem.h +++ b/rtc_base/unixfilesystem.h @@ -14,7 +14,6 @@ #include #include "rtc_base/fileutils.h" -#include "rtc_base/pathutils.h" namespace rtc { @@ -25,20 +24,18 @@ class UnixFilesystem : public FilesystemInterface { // This will attempt to delete the file located at filename. // It will fail with VERIY if you pass it a non-existant file, or a directory. - bool DeleteFile(const Pathname& filename) override; + bool DeleteFile(const std::string& filename) override; // This moves a file from old_path to new_path, where "file" can be a plain // file or directory, which will be moved recursively. // Returns true if function succeeds. - bool MoveFile(const Pathname& old_path, const Pathname& new_path) override; - - // Returns true if a pathname is a directory - bool IsFolder(const Pathname& pathname) override; + bool MoveFile(const std::string& old_path, + const std::string& new_path) override; // Returns true of pathname represents an existing file - bool IsFile(const Pathname& pathname) override; + bool IsFile(const std::string& pathname) override; - bool GetFileSize(const Pathname& path, size_t* size) override; + bool GetFileSize(const std::string& path, size_t* size) override; }; } // namespace rtc diff --git a/rtc_base/win32filesystem.cc b/rtc_base/win32filesystem.cc index cd439660db..5465a5cbb7 100644 --- a/rtc_base/win32filesystem.cc +++ b/rtc_base/win32filesystem.cc @@ -21,7 +21,6 @@ #include "rtc_base/checks.h" #include "rtc_base/fileutils.h" #include "rtc_base/logging.h" -#include "rtc_base/pathutils.h" #include "rtc_base/stream.h" #include "rtc_base/stringutils.h" @@ -34,48 +33,37 @@ namespace rtc { -bool Win32Filesystem::DeleteFile(const Pathname& filename) { - RTC_LOG(LS_INFO) << "Deleting file " << filename.pathname(); +bool Win32Filesystem::DeleteFile(const std::string& filename) { + RTC_LOG(LS_INFO) << "Deleting file " << filename; if (!IsFile(filename)) { RTC_DCHECK(IsFile(filename)); return false; } - return ::DeleteFile(ToUtf16(filename.pathname()).c_str()) != 0; + return ::DeleteFile(ToUtf16(filename).c_str()) != 0; } -bool Win32Filesystem::MoveFile(const Pathname& old_path, - const Pathname& new_path) { +bool Win32Filesystem::MoveFile(const std::string& old_path, + const std::string& new_path) { if (!IsFile(old_path)) { RTC_DCHECK(IsFile(old_path)); return false; } - RTC_LOG(LS_INFO) << "Moving " << old_path.pathname() << " to " - << new_path.pathname(); - return ::MoveFile(ToUtf16(old_path.pathname()).c_str(), - ToUtf16(new_path.pathname()).c_str()) != 0; + RTC_LOG(LS_INFO) << "Moving " << old_path << " to " << new_path; + return ::MoveFile(ToUtf16(old_path).c_str(), ToUtf16(new_path).c_str()) != 0; } -bool Win32Filesystem::IsFolder(const Pathname& path) { +bool Win32Filesystem::IsFile(const std::string& path) { WIN32_FILE_ATTRIBUTE_DATA data = {0}; - if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), - GetFileExInfoStandard, &data)) - return false; - return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == - FILE_ATTRIBUTE_DIRECTORY; -} - -bool Win32Filesystem::IsFile(const Pathname& path) { - WIN32_FILE_ATTRIBUTE_DATA data = {0}; - if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), - GetFileExInfoStandard, &data)) + if (0 == ::GetFileAttributesEx(ToUtf16(path).c_str(), GetFileExInfoStandard, + &data)) return false; return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; } -bool Win32Filesystem::GetFileSize(const Pathname& pathname, size_t* size) { +bool Win32Filesystem::GetFileSize(const std::string& pathname, size_t* size) { WIN32_FILE_ATTRIBUTE_DATA data = {0}; - if (::GetFileAttributesEx(ToUtf16(pathname.pathname()).c_str(), - GetFileExInfoStandard, &data) == 0) + if (::GetFileAttributesEx(ToUtf16(pathname).c_str(), GetFileExInfoStandard, + &data) == 0) return false; *size = data.nFileSizeLow; return true; diff --git a/rtc_base/win32filesystem.h b/rtc_base/win32filesystem.h index d26741e67b..2c27f90575 100644 --- a/rtc_base/win32filesystem.h +++ b/rtc_base/win32filesystem.h @@ -19,21 +19,19 @@ class Win32Filesystem : public FilesystemInterface { public: // This will attempt to delete the path located at filename. // If the path points to a folder, it will fail with VERIFY - bool DeleteFile(const Pathname& filename) override; + bool DeleteFile(const std::string& filename) override; // This moves a file from old_path to new_path. If the new path is on a // different volume than the old, it will attempt to copy and then delete // the folder // Returns true if the file is successfully moved - bool MoveFile(const Pathname& old_path, const Pathname& new_path) override; - - // Returns true if a pathname is a directory - bool IsFolder(const Pathname& pathname) override; + bool MoveFile(const std::string& old_path, + const std::string& new_path) override; // Returns true if a file exists at path - bool IsFile(const Pathname& path) override; + bool IsFile(const std::string& path) override; - bool GetFileSize(const Pathname& path, size_t* size) override; + bool GetFileSize(const std::string& path, size_t* size) override; }; } // namespace rtc diff --git a/test/testsupport/fileutils.cc b/test/testsupport/fileutils.cc index 0eac8d5e0f..a71d8f8db5 100644 --- a/test/testsupport/fileutils.cc +++ b/test/testsupport/fileutils.cc @@ -64,16 +64,12 @@ namespace webrtc { namespace test { -namespace { - #if defined(WEBRTC_WIN) const char* kPathDelimiter = "\\"; #else const char* kPathDelimiter = "/"; #endif -} // namespace - std::string DirName(const std::string& path) { if (path.empty()) return ""; diff --git a/test/testsupport/fileutils.h b/test/testsupport/fileutils.h index 693944e2ae..8a186988d6 100644 --- a/test/testsupport/fileutils.h +++ b/test/testsupport/fileutils.h @@ -25,6 +25,9 @@ namespace test { // to find the project root. extern const char* kCannotFindProjectRootDir; +// Slash or backslash, depending on platform. NUL-terminated string. +extern const char* kPathDelimiter; + // Returns the absolute path to the output directory where log files and other // test artifacts should be put. The output directory is generally a directory // named "out" at the project root. This root is assumed to be two levels above diff --git a/test/testsupport/fileutils_unittest.cc b/test/testsupport/fileutils_unittest.cc index c6dc86deb2..d39f468004 100644 --- a/test/testsupport/fileutils_unittest.cc +++ b/test/testsupport/fileutils_unittest.cc @@ -24,9 +24,6 @@ #ifdef WIN32 #define chdir _chdir -static const char* kPathDelimiter = "\\"; -#else -static const char* kPathDelimiter = "/"; #endif using ::testing::EndsWith; diff --git a/test/testsupport/test_artifacts_unittest.cc b/test/testsupport/test_artifacts_unittest.cc index 267ea93676..df02d27c67 100644 --- a/test/testsupport/test_artifacts_unittest.cc +++ b/test/testsupport/test_artifacts_unittest.cc @@ -16,7 +16,6 @@ #include "rtc_base/file.h" #include "rtc_base/flags.h" -#include "rtc_base/pathutils.h" #include "rtc_base/platform_file.h" #include "test/gtest.h" #include "test/testsupport/fileutils.h" diff --git a/video/video_analyzer.cc b/video/video_analyzer.cc index af28bb92e0..1fd22ff806 100644 --- a/video/video_analyzer.cc +++ b/video/video_analyzer.cc @@ -18,9 +18,9 @@ #include "rtc_base/flags.h" #include "rtc_base/format_macros.h" #include "rtc_base/memory_usage.h" -#include "rtc_base/pathutils.h" #include "system_wrappers/include/cpu_info.h" #include "test/call_test.h" +#include "test/testsupport/fileutils.h" #include "test/testsupport/frame_writer.h" #include "test/testsupport/perf_test.h" #include "test/testsupport/test_artifacts.h" @@ -606,7 +606,7 @@ void VideoAnalyzer::PrintResults() { std::string output_dir; test::GetTestArtifactsDir(&output_dir); std::string output_path = - rtc::Pathname(output_dir, test_label_ + ".jpg").pathname(); + test::JoinFilename(output_dir, test_label_ + ".jpg"); RTC_LOG(LS_INFO) << "Saving worst frame to " << output_path; test::JpegFrameWriter frame_writer(output_path); RTC_CHECK(