00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include "sbuild-dirstream.h"
00023
00024 #include <cerrno>
00025 #include <cstring>
00026
00027 using namespace sbuild;
00028
00029 namespace
00030 {
00031
00032 typedef std::pair<dirstream::error_code,const char *> emap;
00033
00038 emap init_errors[] =
00039 {
00040
00041 emap(dirstream::DIR_OPEN, N_("Failed to open directory '%1%'")),
00042
00043 emap(dirstream::DIR_READ, N_("Failed to read directory '%1%'"))
00044 };
00045
00046 }
00047
00048 template<>
00049 error<dirstream::error_code>::map_type
00050 error<dirstream::error_code>::error_strings
00051 (init_errors,
00052 init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
00053
00054
00055 dirstream::dirstream(std::string const& dirname):
00056 dirname(),
00057 dir(0),
00058 data(),
00059 error_status(true),
00060 eof_status(true)
00061 {
00062 open(dirname);
00063 }
00064
00065
00066 dirstream::~dirstream()
00067 {
00068 close();
00069 }
00070
00071 void
00072 dirstream::open(std::string const& dirname)
00073 {
00074 this->dir = opendir(dirname.c_str());
00075 if (this->dir == 0)
00076 {
00077 this->dirname.clear();
00078 this->error_status = true;
00079 this->eof_status = true;
00080 throw error(dirname, DIR_OPEN, strerror(errno));
00081 }
00082 this->dirname = dirname;
00083 this->error_status = false;
00084 this->eof_status = false;
00085 read();
00086 }
00087
00088 void
00089 dirstream::read(int quantity)
00090 {
00091 int i;
00092
00093 if (this->dir == 0)
00094 return;
00095
00096 for (i = 0; i < quantity; ++i)
00097 {
00098 struct dirent* entry;
00099 errno = 0;
00100 entry = readdir(dir);
00101
00102 if (entry == 0)
00103 {
00104
00105 if (errno)
00106 {
00107 this->error_status = true;
00108 throw error(this->dirname, DIR_READ, strerror(errno));
00109 }
00110 return;
00111 }
00112
00113 direntry newentry(entry);
00114 this->data.push_back(newentry);
00115 }
00116 }
00117
00118 void
00119 dirstream::close()
00120 {
00121 if (this->dir)
00122 closedir(this->dir);
00123
00124 this->dir = 0;
00125 this->data.clear();
00126 this->dirname.clear();
00127 this->error_status = true;
00128 this->eof_status = true;
00129 }
00130
00131
00132 bool
00133 dirstream::eof() const
00134 {
00135 return this->eof_status;
00136 }
00137
00138 bool
00139 dirstream::bad() const
00140 {
00141 return this->error_status;
00142 }
00143
00144 sbuild::dirstream::operator bool ()
00145 {
00146 return !(bad() || eof());
00147 }
00148
00149 bool
00150 sbuild::dirstream::operator ! ()
00151 {
00152 return bad() || eof();
00153 }
00154
00155
00156 dirstream&
00157 sbuild::operator >> (dirstream& stream,
00158 direntry& entry)
00159 {
00160 stream.read();
00161 if (stream && !stream.data.empty())
00162 {
00163 entry = stream.data.front();
00164 stream.data.pop_front();
00165 }
00166 else
00167 {
00168 std::memset(&entry, 0, sizeof(direntry));
00169 stream.eof_status = true;
00170 }
00171
00172 return stream;
00173 }