Files
pip/src/io/pidir.cpp
Пелипенко Иван 51da261a56 PIDir fix PICoutManipulator
git-svn-id: svn://db.shs.com.ru/pip@68 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
2015-04-07 09:40:58 +00:00

437 lines
9.8 KiB
C++
Executable File

/*
PIP - Platform Independent Primitives
Directory
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pidir.h"
//#if !defined(ANDROID)
const PIChar PIDir::separator = '/';
#ifdef QNX
# define _stat_struct_ struct stat
# define _stat_call_ stat
# define _stat_link_ lstat
#else
# define _stat_struct_ struct stat64
# define _stat_call_ stat64
# define _stat_link_ lstat64
#endif
#ifndef WINDOWS
# ifdef ANDROID
# include <dirent.h>
# else
# include <sys/dir.h>
# endif
# include <sys/stat.h>
#endif
/*! \class PIDir
* \brief Local directory
*
* \section PIDir_sec0 Synopsis
* This class provide access to local file. You can manipulate
* binary content or use this class as text stream. To binary
* access there are function \a read(), \a write(), and many
* \a writeBinary() functions. For write variables to file in
* their text representation threr are many "<<" operators.
*
*/
PIDir::PIDir(const PIString & dir) {
setDir(dir);
}
PIDir::PIDir(const PIFile & file) {
setDir(file.path());
if (isExists()) return;
int pos = path_.findLast(separator);
path_.cutRight(path_.size_s() - pos);
}
bool PIDir::operator ==(const PIDir & d) const {
return d.absolutePath() == absolutePath();
}
bool PIDir::isAbsolute() const {
if (path_.isEmpty()) return false;
/*#ifdef WINDOWS
if (path_.size_s() < 2) return false;
return (path_.mid(1, 2).contains(":"));
#else
return (path_[0] == separator);
#endif*/
return (path_[0] == separator);
}
PIString PIDir::path() const {
#ifdef WINDOWS
if (path_.startsWith(separator)) {
if (path_.length() == 1)
return separator;
else
return path_.mid(1);
} else
#endif
return path_;
}
PIString PIDir::absolutePath() const {
if (isAbsolute()) {
#ifdef WINDOWS
if (path_.startsWith(separator)) {
if (path_.length() == 1)
return separator;
else
return path_.mid(1);
} else
#endif
return path_;
}
return PIDir(PIDir::current().path() + separator + path_).path();
}
PIDir & PIDir::cleanPath() {
PIString p(path_);
if (p.size() == 0) {
path_ = ".";
return *this;
}
PIString sep = PIString(separator);
path_.replaceAll(sep + sep, sep);
bool is_abs = isAbsolute();
PIStringList l = PIString(p).split(separator);
l.removeAll(".");
l.removeAll("");
for (int i = 0; i < l.size_s() - 1; ++i) {
if (l[i] != ".." && l[i + 1] == "..") {
l.remove(i, 2);
i -= 2;
if (i < -1) i = -1;
}
}
if (is_abs)
while (!l.isEmpty()) {
if (l.front() == "..")
l.pop_front();
else
break;
}
path_ = l.join(separator);
if (is_abs)
path_.prepend(separator);
if (path_.isEmpty()) path_ = ".";
return *this;
}
PIString PIDir::relative(const PIString & path) const {
PIDir td(path);
PIStringList dl(absolutePath().split(separator)), pl(td.absolutePath().split(separator)), rl;
while (!dl.isEmpty() && !pl.isEmpty()) {
if (dl.front() != pl.front()) break;
dl.pop_front();
pl.pop_front();
}
for (int i = 0; i < dl.size_s(); ++i)
rl << "..";
rl << pl;
if (rl.isEmpty()) return ".";
return rl.join(separator);
}
PIDir & PIDir::setDir(const PIString & path) {
path_ = path;
#ifdef WINDOWS
path_.replaceAll("\\", separator);
if (path_.length() > 2)
if (path_.mid(1, 2).contains(":"))
path_.prepend(separator);
#endif
cleanPath();
return *this;
}
PIDir & PIDir::cd(const PIString & path) {
if (path_.isEmpty()) return *this;
if (path_.back() != separator) path_ += separator;
path_ += path;
return cleanPath();
}
bool PIDir::make(bool withParents) {
PIDir d = cleanedPath();
PIString tp;
bool is_abs = isAbsolute();
if (withParents) {
PIStringList l = d.path().split(separator);
for (int i = l.size_s() - 1; i >= 0; --i) {
if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator);
else {
tp = separator;
if (!is_abs) tp.push_front('.');
}
//cout << tp << endl;
if (isExists(tp)) {
for (int j = i + 1; j <= l.size_s(); ++j) {
tp = PIStringList(l).remove(j, l.size_s() - j).join(separator);
//cout << tp << endl;
if (makeDir(tp)) continue;
else return false;
}
break;
};
}
return true;
} else
if (makeDir(d.path())) return true;
return false;
}
PIVector<PIFile::FileInfo> PIDir::entries() {
PIVector<PIFile::FileInfo> l;
if (!isExists()) return l;
PIString dp = absolutePath();
PIString p(dp);
if (dp == ".") dp.clear();
else if (!dp.endsWith(separator)) dp += separator;
//piCout << "entries from" << p;
#ifdef WINDOWS
if (dp == separator) {
char letters[1024];
PIFile::FileInfo fi;
DWORD ll = GetLogicalDriveStrings(1023, letters);
PIString clet;
for (int i = 0; i < ll; ++i) {
if (letters[i] == '\0') {
clet.resize(2);
fi.path = clet;
fi.flags = PIFile::FileInfo::Dir;
l << fi;
clet.clear();
} else
clet += PIChar(letters[i]);
}
} else {
WIN32_FIND_DATA fd; memset(&fd, 0, sizeof(fd));
p += "\\*";
void * hf = FindFirstFile((LPCTSTR)(p.data()), &fd);
if (!hf) return l;
bool hdd = false;
do {
PIString fn(fd.cFileName);
if (fn == "..") hdd = true;
l << PIFile::fileInfo(dp + fn);
memset(&fd, 0, sizeof(fd));
} while (FindNextFile(hf, &fd) != 0);
FindClose(hf);
if (!hdd) {
PIFile::FileInfo fi;
fi.path = "..";
fi.flags = PIFile::FileInfo::Dir | PIFile::FileInfo::DotDot;
l.push_front(fi);
}
}
#else
dirent ** list;
int cnt = scandir(
# ifndef QNX
p.data(), &list
# else
const_cast<char*>(p.data()), 0
# endif
, 0,
# if defined(MAC_OS) || defined(ANDROID)
alphasort);
# else
versionsort);
# endif
for (int i = 0; i < cnt; ++i) {
l << PIFile::fileInfo(dp + PIString(list[i]->d_name));
delete list[i];
}
delete list;
#endif
return l;
}
PIVector<PIFile::FileInfo> PIDir::allEntries() {
return allEntries(absolutePath());
}
bool PIDir::isExists(const PIString & path) {
#ifdef WINDOWS
DWORD ret = GetFileAttributes((LPCTSTR)(path.data()));
return (ret != 0xFFFFFFFF) && (ret & FILE_ATTRIBUTE_DIRECTORY);
#else
DIR * dir_ = opendir(path.data());
if (dir_ == 0) return false;
closedir(dir_);
#endif
return true;
}
PIDir PIDir::current() {
char rc[1024];
#ifdef WINDOWS
memset(rc, 0, 1024);
if (GetCurrentDirectory(1024, (LPTSTR)rc) == 0) return PIString();
PIString ret(rc);
ret.replaceAll("\\", PIDir::separator);
ret.prepend(separator);
return PIDir(ret);
#else
if (getcwd(rc, 1024) == 0) return PIString();
#endif
return PIDir(rc);
}
PIDir PIDir::home() {
char * rc = 0;
#ifdef WINDOWS
rc = new char[1024];
memset(rc, 0, 1024);
if (ExpandEnvironmentStrings((LPCTSTR)"%HOMEPATH%", (LPTSTR)rc, 1024) == 0) {
delete[] rc;
return PIDir();
}
PIString s(rc);
s.replaceAll("\\", PIDir::separator);
delete[] rc;
s.prepend(separator);
return PIDir(s);
#else
rc = getenv("HOME");
if (rc == 0) return PIDir();
return PIDir(rc);
#endif
}
PIDir PIDir::temporary() {
char * rc = 0;
#ifdef WINDOWS
rc = new char[1024];
memset(rc, 0, 1024);
int ret = GetTempPath(1024, (LPTSTR)rc);
if (ret == 0) {
delete[] rc;
return PIDir();
}
PIString s(rc);
s.replaceAll("\\", PIDir::separator);
delete[] rc;
s.prepend(separator);
return PIDir(s);
#else
rc = tmpnam(0);
if (rc == 0) return PIDir();
PIString s(rc);
return PIDir(s.left(s.findLast(PIDir::separator)));
#endif
}
PIVector<PIFile::FileInfo> PIDir::allEntries(const PIString &path) {
PIVector<PIFile::FileInfo> ret;
PIVector<PIFile::FileInfo> dirs;
PIDir root;
root.setDir(path);
PIVector<PIFile::FileInfo> cds = root.entries();
piForeachC (PIFile::FileInfo & de, cds) {
//piCout << " open" << de.name();
if (de.name() == "." || de.name() == "..") continue;
if (de.isSymbolicLink()) continue; /// TODO: resolve symlinks
if (de.isDir()) {
dirs.push_front(de);
PIVector<PIFile::FileInfo> td = PIDir(de.path).allEntries();
for (int i = 0; i < td.size_s(); i++) {
if (td[i].isDir()) dirs.push_front(td[i]);
else ret << td[i];
}
} else ret << de;
}
ret.insert(0, dirs);
return ret;
}
bool PIDir::make(const PIString & path, bool withParents) {
PIDir d(path);
if (d.isExists()) return true;
return d.make(withParents);
}
bool PIDir::setCurrent(const PIString & path) {
#ifdef WINDOWS
if (SetCurrentDirectory((LPCTSTR)(path.data())) != 0) return true;
#else
if (chdir(path.data()) == 0) return true;
#endif
printf("[PIDir] setCurrent(\"%s\") error: %s\n", path.data(), errorString().data());
return false;
}
bool PIDir::makeDir(const PIString & path) {
#ifdef WINDOWS
if (CreateDirectory((LPCTSTR)(path.data()), NULL) != 0) return true;
#else
if (mkdir(path.data(), 16877) == 0) return true;
#endif
printf("[PIDir] makeDir(\"%s\") error: %s\n", path.data(), errorString().data());
return false;
}
bool PIDir::removeDir(const PIString & path) {
#ifdef WINDOWS
if (RemoveDirectory((LPCTSTR)(path.data())) != 0) return true;
#else
if (rmdir(path.data()) == 0) return true;
#endif
printf("[PIDir] removeDir(\"%s\") error: %s\n", path.data(), errorString().data());
return false;
}
bool PIDir::renameDir(const PIString & path, const PIString & new_name) {
if (::rename(path.data(), new_name.data()) == 0) return true;
printf("[PIDir] renameDir(\"%s\", \"%s\") error: %s\n", path.data(), new_name.data(), errorString().data());
return false;
}
//#endif