blob: c4a2c30dc832d76aa9cf1ba3ea30ede43643f61c [file] [log] [blame]
henrike@webrtc.org47be73b2014-05-13 18:00:261/*
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>
kjellander1b3c70a2016-04-19 10:03:2316#endif // WEBRTC_WIN
henrike@webrtc.org47be73b2014-05-13 18:00:2617
zijiehe483eaba2016-12-06 23:04:0218#include "webrtc/base/checks.h"
henrike@webrtc.org47be73b2014-05-13 18:00:2619#include "webrtc/base/fileutils.h"
20#include "webrtc/base/logging.h"
21#include "webrtc/base/pathutils.h"
22#include "webrtc/base/stringutils.h"
23#include "webrtc/base/urlencode.h"
24
25namespace rtc {
26
27static const char EMPTY_STR[] = "";
28
29// EXT_DELIM separates a file basename from extension
30const char EXT_DELIM = '.';
31
32// FOLDER_DELIMS separate folder segments and the filename
33const char* const FOLDER_DELIMS = "/\\";
34
35// DEFAULT_FOLDER_DELIM is the preferred delimiter for this platform
kwiberg15b966d2016-09-29 00:42:0136#ifdef WEBRTC_WIN
henrike@webrtc.org47be73b2014-05-13 18:00:2637const char DEFAULT_FOLDER_DELIM = '\\';
kjellander1b3c70a2016-04-19 10:03:2338#else // !WEBRTC_WIN
henrike@webrtc.org47be73b2014-05-13 18:00:2639const char DEFAULT_FOLDER_DELIM = '/';
kjellander1b3c70a2016-04-19 10:03:2340#endif // !WEBRTC_WIN
henrike@webrtc.org47be73b2014-05-13 18:00:2641
42///////////////////////////////////////////////////////////////////////////////
43// Pathname - parsing of pathnames into components, and vice versa
44///////////////////////////////////////////////////////////////////////////////
45
46bool Pathname::IsFolderDelimiter(char ch) {
47 return (NULL != ::strchr(FOLDER_DELIMS, ch));
48}
49
50char Pathname::DefaultFolderDelimiter() {
51 return DEFAULT_FOLDER_DELIM;
52}
53
54Pathname::Pathname()
55 : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
56}
57
kjellander1b3c70a2016-04-19 10:03:2358Pathname::Pathname(const Pathname&) = default;
kwiberg5c731dd2016-04-22 11:59:3159Pathname::Pathname(Pathname&&) = default;
kjellander1b3c70a2016-04-19 10:03:2360
henrike@webrtc.org47be73b2014-05-13 18:00:2661Pathname::Pathname(const std::string& pathname)
62 : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
63 SetPathname(pathname);
64}
65
66Pathname::Pathname(const std::string& folder, const std::string& filename)
67 : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
68 SetPathname(folder, filename);
69}
70
kwiberg5c731dd2016-04-22 11:59:3171Pathname& Pathname::operator=(const Pathname&) = default;
72Pathname& Pathname::operator=(Pathname&&) = default;
73
henrike@webrtc.org47be73b2014-05-13 18:00:2674void Pathname::SetFolderDelimiter(char delimiter) {
zijiehe483eaba2016-12-06 23:04:0275 RTC_DCHECK(IsFolderDelimiter(delimiter));
henrike@webrtc.org47be73b2014-05-13 18:00:2676 folder_delimiter_ = delimiter;
77}
78
79void Pathname::Normalize() {
80 for (size_t i=0; i<folder_.length(); ++i) {
81 if (IsFolderDelimiter(folder_[i])) {
82 folder_[i] = folder_delimiter_;
83 }
84 }
85}
86
87void Pathname::clear() {
88 folder_.clear();
89 basename_.clear();
90 extension_.clear();
91}
92
93bool Pathname::empty() const {
94 return folder_.empty() && basename_.empty() && extension_.empty();
95}
96
97std::string Pathname::pathname() const {
98 std::string pathname(folder_);
99 pathname.append(basename_);
100 pathname.append(extension_);
101 if (pathname.empty()) {
102 // Instead of the empty pathname, return the current working directory.
103 pathname.push_back('.');
104 pathname.push_back(folder_delimiter_);
105 }
106 return pathname;
107}
108
109std::string Pathname::url() const {
110 std::string s = "file:///";
111 for (size_t i=0; i<folder_.length(); ++i) {
112 if (IsFolderDelimiter(folder_[i]))
113 s += '/';
114 else
115 s += folder_[i];
116 }
117 s += basename_;
118 s += extension_;
119 return UrlEncodeStringForOnlyUnsafeChars(s);
120}
121
122void Pathname::SetPathname(const std::string& pathname) {
123 std::string::size_type pos = pathname.find_last_of(FOLDER_DELIMS);
124 if (pos != std::string::npos) {
125 SetFolder(pathname.substr(0, pos + 1));
126 SetFilename(pathname.substr(pos + 1));
127 } else {
128 SetFolder(EMPTY_STR);
129 SetFilename(pathname);
130 }
131}
132
133void Pathname::SetPathname(const std::string& folder,
134 const std::string& filename) {
135 SetFolder(folder);
136 SetFilename(filename);
137}
138
139void Pathname::AppendPathname(const std::string& pathname) {
140 std::string full_pathname(folder_);
141 full_pathname.append(pathname);
142 SetPathname(full_pathname);
143}
144
145std::string Pathname::folder() const {
146 return folder_;
147}
148
149std::string Pathname::folder_name() const {
150 std::string::size_type pos = std::string::npos;
151 if (folder_.size() >= 2) {
152 pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2);
153 }
154 if (pos != std::string::npos) {
155 return folder_.substr(pos + 1);
156 } else {
157 return folder_;
158 }
159}
160
161std::string Pathname::parent_folder() const {
162 std::string::size_type pos = std::string::npos;
163 if (folder_.size() >= 2) {
164 pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2);
165 }
166 if (pos != std::string::npos) {
167 return folder_.substr(0, pos + 1);
168 } else {
169 return EMPTY_STR;
170 }
171}
172
173void Pathname::SetFolder(const std::string& folder) {
174 folder_.assign(folder);
175 // Ensure folder ends in a path delimiter
176 if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) {
177 folder_.push_back(folder_delimiter_);
178 }
179}
180
181void Pathname::AppendFolder(const std::string& folder) {
182 folder_.append(folder);
183 // Ensure folder ends in a path delimiter
184 if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) {
185 folder_.push_back(folder_delimiter_);
186 }
187}
188
189std::string Pathname::basename() const {
190 return basename_;
191}
192
193bool Pathname::SetBasename(const std::string& basename) {
194 if(basename.find_first_of(FOLDER_DELIMS) != std::string::npos) {
195 return false;
196 }
197 basename_.assign(basename);
198 return true;
199}
200
201std::string Pathname::extension() const {
202 return extension_;
203}
204
205bool Pathname::SetExtension(const std::string& extension) {
206 if (extension.find_first_of(FOLDER_DELIMS) != std::string::npos ||
207 extension.find_first_of(EXT_DELIM, 1) != std::string::npos) {
208 return false;
209 }
210 extension_.assign(extension);
211 // Ensure extension begins with the extension delimiter
212 if (!extension_.empty() && (extension_[0] != EXT_DELIM)) {
213 extension_.insert(extension_.begin(), EXT_DELIM);
214 }
215 return true;
216}
217
218std::string Pathname::filename() const {
219 std::string filename(basename_);
220 filename.append(extension_);
221 return filename;
222}
223
224bool Pathname::SetFilename(const std::string& filename) {
225 std::string::size_type pos = filename.rfind(EXT_DELIM);
226 if ((pos == std::string::npos) || (pos == 0)) {
227 return SetExtension(EMPTY_STR) && SetBasename(filename);
228 } else {
229 return SetExtension(filename.substr(pos)) && SetBasename(filename.substr(0, pos));
230 }
231}
232
233#if defined(WEBRTC_WIN)
Peter Boström07e22e62015-10-07 10:23:21234bool Pathname::GetDrive(char* drive, uint32_t bytes) const {
henrike@webrtc.org47be73b2014-05-13 18:00:26235 return GetDrive(drive, bytes, folder_);
236}
237
238// static
Peter Boström07e22e62015-10-07 10:23:21239bool Pathname::GetDrive(char* drive,
240 uint32_t bytes,
henrike@webrtc.org47be73b2014-05-13 18:00:26241 const std::string& pathname) {
242 // need at lease 4 bytes to save c:
243 if (bytes < 4 || pathname.size() < 3) {
244 return false;
245 }
246
247 memcpy(drive, pathname.c_str(), 3);
248 drive[3] = 0;
249 // sanity checking
250 return (isalpha(drive[0]) &&
251 drive[1] == ':' &&
252 drive[2] == '\\');
253}
254#endif
255
256///////////////////////////////////////////////////////////////////////////////
257
258} // namespace rtc