2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @author Tomasz Iwanek (t.iwanek@samsung.com)
22 #include "dpl/utils/path.h"
24 #include <dpl/utils/wrt_utility.h>
26 #include <dpl/scoped_free.h>
27 #include <dpl/errno_string.h>
28 #include <dpl/file_input.h>
29 #include <dpl/file_output.h>
38 Path::Iterator::Iterator() //end iterator by default
42 Path::Iterator::Iterator(const char * str)
44 m_root = std::shared_ptr<Path>(new Path(str));
45 m_dir = std::shared_ptr<DIR>(opendir(str), [](DIR * d){ if(d)closedir(d); }); //custom delete
46 if(m_dir.get() == NULL)
48 ThrowMsg(NotDirectory, "Not directory");
53 Path::Iterator& Path::Iterator::operator++()
59 Path::Iterator Path::Iterator::operator++(int)
61 Path::Iterator copy(*this);
66 void Path::Iterator::ReadNext()
68 struct dirent * entry = readdir(m_dir.get());
69 while(entry && (strcmp(entry->d_name, ".") == 0 ||
70 strcmp(entry->d_name, "..") == 0))
72 entry = readdir(m_dir.get());
76 m_path = std::shared_ptr<Path>(new Path(*m_root));
77 m_path->Append(entry->d_name);
79 else //transform into end iterator
86 bool Path::Iterator::operator==(const Path::Iterator& rhs) const
88 if(m_dir.get() == NULL)
90 if(rhs.m_dir.get() == NULL) return true;
95 if(rhs.m_dir.get() == NULL) return false;
97 return *m_path == *rhs.m_path;
100 bool Path::Iterator::operator!=(const Path::Iterator& rhs) const
102 return !this->operator==(rhs);
105 const Path & Path::Iterator::operator*()
110 const Path * Path::Iterator::operator->()
115 Path::Path(const DPL::String & str)
117 Construct(ToUTF8String(str));
120 Path::Path(const std::string & str)
125 Path::Path(const char * str)
127 Construct(std::string(str));
130 void Path::Construct(const std::string & src)
132 if(src.empty()) ThrowMsg(EmptyPath, "Path cannot be empty");
135 DPL::ScopedFree<char> root(getcwd(NULL,0));
136 Tokenize(std::string(root.Get()), "\\/", std::inserter(m_parts, m_parts.begin()), true);
138 Tokenize(src, "\\/", std::inserter(m_parts, m_parts.end()), true);
141 Path::Path() //for private usage
145 std::string Path::DirectoryName() const
147 if(m_parts.empty()) ThrowMsg(InternalError, "Asking DirectoryName for root directory");
148 std::string ret = Join(m_parts.begin(), --m_parts.end(), "/");
149 return std::string("/") + ret;
152 std::string Path::Basename() const
154 if(m_parts.empty()) return "";
155 else return m_parts.back();
158 std::string Path::Fullpath() const
160 std::string ret = Join(m_parts.begin(), m_parts.end(), "/");
161 return std::string ("/") + ret;
165 Path::Iterator Path::begin() const
169 return Iterator(Fullpath().c_str());
173 ThrowMsg(NotDirectory, "Cannot iterate not a directory");
177 Path::Iterator Path::end() const
183 bool Path::Exists() const
186 return (0 == lstat(Fullpath().c_str(), &tmp));
189 bool Path::IsDir() const
192 if (-1 == lstat(Fullpath().c_str(), &tmp))
194 ThrowMsg(NotExists, DPL::GetErrnoString());
196 return S_ISDIR(tmp.st_mode);
199 bool Path::IsFile() const
202 if (-1 == lstat(Fullpath().c_str(), &tmp))
204 ThrowMsg(NotExists, DPL::GetErrnoString());
206 return S_ISREG(tmp.st_mode);
209 bool Path::IsSymlink() const
212 if (-1 == lstat(Fullpath().c_str(), &tmp))
214 ThrowMsg(NotExists, DPL::GetErrnoString());
216 return S_ISLNK(tmp.st_mode);
219 bool Path::operator==(const Path & other) const
221 return m_parts == other.m_parts;
224 bool Path::operator!=(const Path & other) const
226 return m_parts != other.m_parts;
229 Path Path::operator/(const DPL::String& part) const
232 newOne.Append(ToUTF8String(part));
236 Path Path::operator/(const std::string& part) const
243 Path Path::operator/(const char * part) const
246 newOne.Append(std::string(part));
250 Path & Path::operator/=(const DPL::String& part)
252 Append(ToUTF8String(part));
255 Path & Path::operator/=(const std::string& part)
260 Path & Path::operator/=(const char * part)
262 Append(std::string(part));
265 void Path::Append(const std::string& part)
267 std::vector<std::string> tokens;
268 Tokenize(part, "\\/", std::inserter(tokens, tokens.end()), true);
269 std::copy(tokens.begin(), tokens.end(), std::inserter(m_parts, m_parts.end()));
272 void MakeDir(const Path & path, mode_t mode)
274 if(!WrtUtilMakeDir(path.Fullpath(), mode)) ThrowMsg(Path::OperationFailed, "Cannot make directory");
277 void MakeEmptyFile(const Path & path)
279 std::string fp = path.Fullpath();
280 FILE* fd = fopen(fp.c_str(), "wx");
284 if(lstat(fp.c_str(), &st) == 0)
286 ThrowMsg(Path::AlreadyExists, "File already exists");
290 ThrowMsg(Path::OperationFailed, "Operation failed");
296 void Remove(const Path & path)
298 if(!WrtUtilRemove(path.Fullpath())) ThrowMsg(Path::OperationFailed, "Cannot remove path");
301 void Rename(const Path & from, const Path & to)
308 if( (code = rename(from.Fullpath().c_str(), to.Fullpath().c_str())) )
314 DPL::FileInput in(from.Fullpath());
315 DPL::FileOutput out(to.Fullpath());
316 DPL::Copy(&in, &out);
318 Catch(DPL::FileInput::Exception::Base)
320 ThrowMsg(Path::OperationFailed, "Cannot open input file " << from.Fullpath());
322 Catch(DPL::FileOutput::Exception::Base)
324 ThrowMsg(Path::OperationFailed, "Cannot open output file " << to.Fullpath());
329 ThrowMsg(Path::OperationFailed, DPL::GetErrnoString());
334 bool Exists(const Path & path)
336 return path.Exists();
343 std::ostream & operator<<(std::ostream & str, const DPL::Utils::Path & path)
345 str << path.Fullpath();
349 //TODO: uncomment when used defiend literals are supported
350 ///DPL::Utils::Path operator""p(const char * str, size_t)
352 // return DPL::Utils::Path(str);