Line data Source code
1 : /*
2 : * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #if defined(WEBRTC_WIN)
12 : #include "webrtc/base/win32.h"
13 : #include <shellapi.h>
14 : #include <shlobj.h>
15 : #include <tchar.h>
16 : #endif // WEBRTC_WIN
17 :
18 : #include "webrtc/base/checks.h"
19 : #include "webrtc/base/fileutils.h"
20 : #include "webrtc/base/logging.h"
21 : #include "webrtc/base/pathutils.h"
22 : #include "webrtc/base/stringutils.h"
23 :
24 : namespace rtc {
25 :
26 : static const char EMPTY_STR[] = "";
27 :
28 : // EXT_DELIM separates a file basename from extension
29 : const char EXT_DELIM = '.';
30 :
31 : // FOLDER_DELIMS separate folder segments and the filename
32 : const char* const FOLDER_DELIMS = "/\\";
33 :
34 : // DEFAULT_FOLDER_DELIM is the preferred delimiter for this platform
35 : #ifdef WEBRTC_WIN
36 : const char DEFAULT_FOLDER_DELIM = '\\';
37 : #else // !WEBRTC_WIN
38 : const char DEFAULT_FOLDER_DELIM = '/';
39 : #endif // !WEBRTC_WIN
40 :
41 : ///////////////////////////////////////////////////////////////////////////////
42 : // Pathname - parsing of pathnames into components, and vice versa
43 : ///////////////////////////////////////////////////////////////////////////////
44 :
45 0 : bool Pathname::IsFolderDelimiter(char ch) {
46 0 : return (NULL != ::strchr(FOLDER_DELIMS, ch));
47 : }
48 :
49 0 : char Pathname::DefaultFolderDelimiter() {
50 0 : return DEFAULT_FOLDER_DELIM;
51 : }
52 :
53 0 : Pathname::Pathname()
54 0 : : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
55 0 : }
56 :
57 : Pathname::Pathname(const Pathname&) = default;
58 : Pathname::Pathname(Pathname&&) = default;
59 :
60 0 : Pathname::Pathname(const std::string& pathname)
61 0 : : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
62 0 : SetPathname(pathname);
63 0 : }
64 :
65 0 : Pathname::Pathname(const std::string& folder, const std::string& filename)
66 0 : : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
67 0 : SetPathname(folder, filename);
68 0 : }
69 :
70 : Pathname& Pathname::operator=(const Pathname&) = default;
71 : Pathname& Pathname::operator=(Pathname&&) = default;
72 :
73 0 : void Pathname::SetFolderDelimiter(char delimiter) {
74 0 : RTC_DCHECK(IsFolderDelimiter(delimiter));
75 0 : folder_delimiter_ = delimiter;
76 0 : }
77 :
78 0 : void Pathname::Normalize() {
79 0 : for (size_t i=0; i<folder_.length(); ++i) {
80 0 : if (IsFolderDelimiter(folder_[i])) {
81 0 : folder_[i] = folder_delimiter_;
82 : }
83 : }
84 0 : }
85 :
86 0 : void Pathname::clear() {
87 0 : folder_.clear();
88 0 : basename_.clear();
89 0 : extension_.clear();
90 0 : }
91 :
92 0 : bool Pathname::empty() const {
93 0 : return folder_.empty() && basename_.empty() && extension_.empty();
94 : }
95 :
96 0 : std::string Pathname::pathname() const {
97 0 : std::string pathname(folder_);
98 0 : pathname.append(basename_);
99 0 : pathname.append(extension_);
100 0 : if (pathname.empty()) {
101 : // Instead of the empty pathname, return the current working directory.
102 0 : pathname.push_back('.');
103 0 : pathname.push_back(folder_delimiter_);
104 : }
105 0 : return pathname;
106 : }
107 :
108 0 : void Pathname::SetPathname(const std::string& pathname) {
109 0 : std::string::size_type pos = pathname.find_last_of(FOLDER_DELIMS);
110 0 : if (pos != std::string::npos) {
111 0 : SetFolder(pathname.substr(0, pos + 1));
112 0 : SetFilename(pathname.substr(pos + 1));
113 : } else {
114 0 : SetFolder(EMPTY_STR);
115 0 : SetFilename(pathname);
116 : }
117 0 : }
118 :
119 0 : void Pathname::SetPathname(const std::string& folder,
120 : const std::string& filename) {
121 0 : SetFolder(folder);
122 0 : SetFilename(filename);
123 0 : }
124 :
125 0 : void Pathname::AppendPathname(const std::string& pathname) {
126 0 : std::string full_pathname(folder_);
127 0 : full_pathname.append(pathname);
128 0 : SetPathname(full_pathname);
129 0 : }
130 :
131 0 : std::string Pathname::folder() const {
132 0 : return folder_;
133 : }
134 :
135 0 : std::string Pathname::folder_name() const {
136 0 : std::string::size_type pos = std::string::npos;
137 0 : if (folder_.size() >= 2) {
138 0 : pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2);
139 : }
140 0 : if (pos != std::string::npos) {
141 0 : return folder_.substr(pos + 1);
142 : } else {
143 0 : return folder_;
144 : }
145 : }
146 :
147 0 : std::string Pathname::parent_folder() const {
148 0 : std::string::size_type pos = std::string::npos;
149 0 : if (folder_.size() >= 2) {
150 0 : pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2);
151 : }
152 0 : if (pos != std::string::npos) {
153 0 : return folder_.substr(0, pos + 1);
154 : } else {
155 0 : return EMPTY_STR;
156 : }
157 : }
158 :
159 0 : void Pathname::SetFolder(const std::string& folder) {
160 0 : folder_.assign(folder);
161 : // Ensure folder ends in a path delimiter
162 0 : if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) {
163 0 : folder_.push_back(folder_delimiter_);
164 : }
165 0 : }
166 :
167 0 : void Pathname::AppendFolder(const std::string& folder) {
168 0 : folder_.append(folder);
169 : // Ensure folder ends in a path delimiter
170 0 : if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) {
171 0 : folder_.push_back(folder_delimiter_);
172 : }
173 0 : }
174 :
175 0 : std::string Pathname::basename() const {
176 0 : return basename_;
177 : }
178 :
179 0 : bool Pathname::SetBasename(const std::string& basename) {
180 0 : if(basename.find_first_of(FOLDER_DELIMS) != std::string::npos) {
181 0 : return false;
182 : }
183 0 : basename_.assign(basename);
184 0 : return true;
185 : }
186 :
187 0 : std::string Pathname::extension() const {
188 0 : return extension_;
189 : }
190 :
191 0 : bool Pathname::SetExtension(const std::string& extension) {
192 0 : if (extension.find_first_of(FOLDER_DELIMS) != std::string::npos ||
193 0 : extension.find_first_of(EXT_DELIM, 1) != std::string::npos) {
194 0 : return false;
195 : }
196 0 : extension_.assign(extension);
197 : // Ensure extension begins with the extension delimiter
198 0 : if (!extension_.empty() && (extension_[0] != EXT_DELIM)) {
199 0 : extension_.insert(extension_.begin(), EXT_DELIM);
200 : }
201 0 : return true;
202 : }
203 :
204 0 : std::string Pathname::filename() const {
205 0 : std::string filename(basename_);
206 0 : filename.append(extension_);
207 0 : return filename;
208 : }
209 :
210 0 : bool Pathname::SetFilename(const std::string& filename) {
211 0 : std::string::size_type pos = filename.rfind(EXT_DELIM);
212 0 : if ((pos == std::string::npos) || (pos == 0)) {
213 0 : return SetExtension(EMPTY_STR) && SetBasename(filename);
214 : } else {
215 0 : return SetExtension(filename.substr(pos)) && SetBasename(filename.substr(0, pos));
216 : }
217 : }
218 :
219 : #if defined(WEBRTC_WIN)
220 : bool Pathname::GetDrive(char* drive, uint32_t bytes) const {
221 : return GetDrive(drive, bytes, folder_);
222 : }
223 :
224 : // static
225 : bool Pathname::GetDrive(char* drive,
226 : uint32_t bytes,
227 : const std::string& pathname) {
228 : // need at lease 4 bytes to save c:
229 : if (bytes < 4 || pathname.size() < 3) {
230 : return false;
231 : }
232 :
233 : memcpy(drive, pathname.c_str(), 3);
234 : drive[3] = 0;
235 : // sanity checking
236 : return (isalpha(drive[0]) &&
237 : drive[1] == ':' &&
238 : drive[2] == '\\');
239 : }
240 : #endif
241 :
242 : ///////////////////////////////////////////////////////////////////////////////
243 :
244 : } // namespace rtc
|