filesystem module enhancements

master
Daniel Kolesa 2015-09-05 03:35:07 +01:00
parent d0662f2b08
commit baaa1e790d
1 changed files with 51 additions and 29 deletions

View File

@ -167,6 +167,8 @@ private:
struct DirectoryRange; struct DirectoryRange;
struct DirectoryStream { struct DirectoryStream {
friend struct DirectoryRange;
DirectoryStream(): p_d(), p_path(), p_owned(false) {} DirectoryStream(): p_d(), p_path(), p_owned(false) {}
DirectoryStream(const DirectoryStream &) = delete; DirectoryStream(const DirectoryStream &) = delete;
DirectoryStream(DirectoryStream &&s): p_d(s.p_d), p_path(move(s.p_path)), DirectoryStream(DirectoryStream &&s): p_d(s.p_d), p_path(move(s.p_path)),
@ -208,15 +210,17 @@ struct DirectoryStream {
p_owned = false; p_owned = false;
} }
bool seek(long offset) { long size() const {
if (!p_d) return false;
seekdir(p_d, offset);
return true;
}
long tell() const {
if (!p_d) return -1; if (!p_d) return -1;
return telldir(p_d); long cs = telldir(p_d);
if (cs < 0) return cs;
seekdir(p_d, 0);
long ret = 0;
struct dirent *rd = nullptr;
while ((rd = readdir(p_d)))
ret += (strcmp(rd->d_name, ".") && strcmp(rd->d_name, ".."));
seekdir(p_d, cs);
return ret;
} }
bool rewind() { bool rewind() {
@ -246,53 +250,71 @@ struct DirectoryStream {
DirectoryRange iter(); DirectoryRange iter();
private: private:
bool compare(const DirectoryStream &ds) {
if (!p_d) return !ds.p_d;
return (p_d == ds.p_d) && (telldir(p_d) == telldir(ds.p_d));
}
bool empty(long n) const {
return !p_d || (telldir(p_d) >= n);
}
bool pop_front() const {
if (!p_d) return false;
long cs = telldir(p_d);
if (cs < 0) return false;
seekdir(p_d, cs + 1);
return telldir(p_d) == (cs + 1);
}
void push_front() const {
if (!p_d) return;
long cs = telldir(p_d);
if (cs < 0) return;
seekdir(p_d, cs - 1);
}
DIR *p_d; DIR *p_d;
String p_path; String p_path;
bool p_owned; bool p_owned;
}; };
struct DirectoryRange: InputRange< struct DirectoryRange: InputRange<
DirectoryRange, InputRangeTag, FileInfo, FileInfo &, Size, long DirectoryRange, InputRangeTag, FileInfo, FileInfo, Size, long
> { > {
DirectoryRange() = delete; DirectoryRange() = delete;
DirectoryRange(DirectoryStream &s): p_stream(&s) { DirectoryRange(DirectoryStream &s): p_stream(&s), p_ssize(s.size()) {}
p_curr = move(s.read());
}
DirectoryRange(const DirectoryRange &r): DirectoryRange(const DirectoryRange &r):
p_stream(r.p_stream), p_curr(r.p_curr) {} p_stream(r.p_stream), p_ssize(r.p_ssize) {}
DirectoryRange(DirectoryRange &&r): p_stream(r.p_stream),
p_curr(move(r.p_curr)) {
r.p_stream = nullptr;
}
DirectoryRange &operator=(const DirectoryRange &) = delete; DirectoryRange &operator=(const DirectoryRange &r) {
DirectoryRange &operator=(DirectoryRange &&r) { p_stream = r.p_stream;
detail::swap_adl(p_stream, r.p_stream); p_ssize = r.p_ssize;
detail::swap_adl(p_curr, r.p_curr);
return *this; return *this;
} }
bool empty() const { bool empty() const {
return p_curr.type() == FileType::unknown; return p_stream->empty(p_ssize);
} }
bool pop_front() { bool pop_front() {
if (empty()) return false; return p_stream->pop_front();
p_curr = move(p_stream->read());
return empty();
} }
FileInfo &front() const { FileInfo front() const {
return p_curr; FileInfo ret(p_stream->read());
p_stream->push_front();
return ret;
} }
bool equals_front(const DirectoryRange &s) const { bool equals_front(const DirectoryRange &s) const {
return p_stream->tell() == s.p_stream->tell(); if (!p_stream) return !s.p_stream;
return p_stream->compare(*s.p_stream);
} }
private: private:
DirectoryStream *p_stream; DirectoryStream *p_stream;
mutable FileInfo p_curr; long p_ssize;
}; };
DirectoryRange DirectoryStream::iter() { DirectoryRange DirectoryStream::iter() {