Mercurial > code
diff C++/modules/Directory/Directory.cpp @ 334:0b576ee64d45
* Create brand new hierarchy
* Rename DynLib to Dynlib
* Remove some warnings
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 08 Mar 2015 14:26:33 +0100 |
parents | C++/Directory.cpp@24085fae3162 |
children | 83ef77841ff1 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/modules/Directory/Directory.cpp Sun Mar 08 14:26:33 2015 +0100 @@ -0,0 +1,189 @@ +/* + * Directory.cpp -- open and read directories + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sstream> +#include <stdexcept> + +#include "Directory.h" + +#if defined(_WIN32) +# include <Windows.h> +#else +# include <cstring> +# include <cerrno> + +# include <sys/types.h> +# include <dirent.h> +#endif + +#if defined(_WIN32) + +namespace { + +std::string systemError() +{ + LPSTR error = nullptr; + std::string errmsg = "Unknown error"; + + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&error, 0, NULL); + + if (error) { + errmsg = std::string(error); + LocalFree(error); + } + + return errmsg; +} + +} + +void Directory::systemLoad(const std::string &path, int flags) +{ + std::ostringstream oss; + HANDLE handle; + WIN32_FIND_DATA fdata; + + oss << path << "\\*"; + handle = FindFirstFile(oss.str().c_str(), &fdata); + + if (handle == nullptr) + throw std::runtime_error(systemError()); + + do { + Entry entry; + + entry.name = fdata.cFileName; + if ((flags & Directory::NotDot) && entry.name == ".") + continue; + if ((flags & Directory::NotDotDot) && entry.name == "..") + continue; + + switch (fdata.dwFileAttributes) { + case FILE_ATTRIBUTE_DIRECTORY: + entry.type = Dir; + break; + case FILE_ATTRIBUTE_NORMAL: + entry.type = File; + break; + case FILE_ATTRIBUTE_REPARSE_POINT: + entry.type = Link; + break; + default: + break; + } + + m_list.push_back(entry); + } while (FindNextFile(handle, &fdata) != 0); + + FindClose(handle); +} + +#else + +void Directory::systemLoad(const std::string &path, int flags) +{ + DIR *dp; + struct dirent *ent; + + if ((dp = opendir(path.c_str())) == nullptr) + throw std::runtime_error(strerror(errno)); + + while ((ent = readdir(dp)) != nullptr) { + Entry entry; + + entry.name = ent->d_name; + if ((flags & Directory::NotDot) && entry.name == ".") + continue; + if ((flags & Directory::NotDotDot) && entry.name == "..") + continue; + + switch (ent->d_type) { + case DT_DIR: + entry.type = Dir; + break; + case DT_REG: + entry.type = File; + break; + case DT_LNK: + entry.type = Link; + break; + default: + break; + } + + m_list.push_back(entry); + } + + closedir(dp); +} + +#endif + +Directory::Entry::Entry() + : type(Unknown) +{ +} + +bool operator==(const Directory::Entry &e1, const Directory::Entry &e2) +{ + return e1.name == e2.name && e1.type == e2.type; +} + +Directory::Directory() +{ +} + +Directory::Directory(const std::string &path, int flags) +{ + systemLoad(path, flags); +} + +Directory::List::iterator Directory::begin() +{ + return m_list.begin(); +} + +Directory::List::const_iterator Directory::cbegin() const +{ + return m_list.cbegin(); +} + +Directory::List::iterator Directory::end() +{ + return m_list.end(); +} + +Directory::List::const_iterator Directory::cend() const +{ + return m_list.cend(); +} + +int Directory::count() const +{ + return m_list.size(); +} + +bool operator==(const Directory &d1, const Directory &d2) +{ + return d1.m_list == d2.m_list; +}