00001 #ifndef _MIMETIC_OS_DIRECTORY_H_
00002 #define _MIMETIC_OS_DIRECTORY_H_
00003 #include <string>
00004 #include <iterator>
00005 #include <mimetic/config.h>
00006 #ifdef HAVE_DIRENT_H
00007 #include <dirent.h>
00008 #endif
00009 #include <unistd.h>
00010 #include <sys/stat.h>
00011
00012 namespace mimetic
00013 {
00014
00015 class Directory
00016 {
00017 public:
00018 struct DirEntry
00019 {
00020 enum Type { Unknown, RegularFile, Directory, Link };
00021 DirEntry(): type(Unknown) {}
00022 std::string name;
00023 Type type;
00024 };
00025 friend class iterator;
00026 struct iterator: public std::iterator<std::forward_iterator_tag, DirEntry>
00027 {
00028 iterator()
00029 : m_dirp(0), m_dirh(0), m_eoi(true)
00030 {
00031 }
00032 iterator(Directory* dirp)
00033 : m_dirp(dirp), m_eoi(false)
00034 {
00035 m_dirh = opendir(m_dirp->m_path.c_str());
00036 if(m_dirh)
00037 {
00038 m_dirent = readdir(m_dirh);
00039 setDirent(m_dirent);
00040 } else {
00041
00042 m_dirp = 0;
00043 m_dirh = 0;
00044 m_eoi = true;
00045 }
00046 }
00047 ~iterator()
00048 {
00049 if(m_dirh)
00050 closedir(m_dirh);
00051 }
00052 const DirEntry& operator*() const
00053 {
00054 return m_de;
00055 }
00056 const DirEntry* operator->() const
00057 {
00058 return &m_de;
00059 }
00060 iterator& operator++()
00061 {
00062 if((m_dirent = readdir(m_dirh)) == NULL)
00063 {
00064 m_eoi = true;
00065 return *this;
00066 }
00067 setDirent(m_dirent);
00068 return *this;
00069 }
00070 iterator operator++(int)
00071 {
00072 iterator it = *this;
00073 ++*this;
00074 return it;
00075 }
00076 bool operator==(const iterator& right)
00077 {
00078 if(m_eoi && right.m_eoi)
00079 return true;
00080
00081 return
00082 m_eoi == right.m_eoi &&
00083 m_dirp->m_path == right.m_dirp->m_path &&
00084 m_dirent && right.m_dirent &&
00085 #ifdef _DIRENT_HAVE_D_TYPE
00086 m_dirent->d_type == right.m_dirent->d_type &&
00087 #endif
00088 std::string(m_dirent->d_name) == right.m_dirent->d_name;
00089 }
00090 bool operator!=(const iterator& right)
00091 {
00092 return !operator==(right);
00093 }
00094 private:
00095 void setDirent(struct dirent* dent)
00096 {
00097 m_de.name = dent->d_name;
00098 m_de.type = DirEntry::Unknown;
00099 #ifdef _DIRENT_HAVE_D_TYPE
00100 switch(dent->d_type)
00101 {
00102 case DT_DIR:
00103 m_de.type = DirEntry::Directory;
00104 break;
00105 case DT_REG:
00106 m_de.type = DirEntry::RegularFile;
00107 break;
00108 case DT_LNK:
00109 m_de.type = DirEntry::Link;
00110 break;
00111 }
00112 #endif
00113 }
00114 Directory* m_dirp;
00115 DIR* m_dirh;
00116 bool m_eoi;
00117 DirEntry m_de;
00118 struct dirent* m_dirent;
00119 };
00120
00121 Directory(const std::string& dir)
00122 : m_path(dir)
00123 {
00124 }
00125 ~Directory()
00126 {
00127 }
00128 iterator begin()
00129 { return iterator(this); }
00130 iterator end()
00131 { return iterator(); };
00132 bool exists() const
00133 {
00134 struct stat st;
00135 return stat(m_path.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
00136 }
00137 static bool exists(const std::string& dname)
00138 {
00139 struct stat st;
00140 return stat(dname.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
00141 }
00142 static bool create(const std::string& dname)
00143 {
00144 if(!exists(dname))
00145 return mkdir(dname.c_str(), 0755) == 0;
00146 else
00147 return 0;
00148 }
00149 static bool remove(const std::string& dname)
00150 {
00151 if(!exists(dname))
00152 return 0;
00153 else
00154 return rmdir(dname.c_str()) == 0;
00155 }
00156 const std::string& path() const
00157 {
00158 return m_path;
00159 }
00160 private:
00161 std::string m_path;
00162 };
00163
00164 }
00165
00166 #endif
00167