#include <iostream>
#include <vector>
#include <string>
class Visitor;
class Entry {
public:
virtual ~Entry() {};
virtual std::string getName() const = 0;
virtual size_t getSize() = 0;
virtual size_t accept(Visitor *v) = 0;
};
template <class T>
class Iterator {
public:
virtual ~Iterator() {}
virtual bool hasNext() = 0;
virtual T next() = 0;
};
template <class T>
class VectorIterator : public Iterator<T> {
std::vector<T> &v;
size_t index = 0;
public:
VectorIterator(std::vector<T> &v) : v(v) {}
bool hasNext() override {
if (index < v.size())
return true;
else
return false;
}
T next() {
T retvalue = v[index];
index++;
return retvalue;
}
};
class File : public Entry {
std::string name;
size_t size;
public:
File(std::string name, size_t size) : name(name), size(size) {}
std::string getName() const override { return name; }
size_t getSize() override { return size; }
size_t accept(Visitor *v) override;
};
class Directory : public Entry {
std::string name;
std::vector<Entry *> v;
public:
Directory(std::string name) : name(name) {}
~Directory() {
for (auto p : v) delete p;
}
std::string getName() const override { return name; }
size_t getSize() override;
size_t accept(Visitor *v) override;
void treePrint();
void add(Entry *entry) { v.push_back(entry); }
Iterator<Entry *> *iterator() { return new VectorIterator<Entry *>(v); }
};
class Visitor {
public:
virtual ~Visitor() {}
virtual size_t visit(File *) = 0;
virtual size_t visit(Directory *) = 0;
};
size_t File::accept(Visitor *v) { return v->visit(this); }
size_t Directory::accept(Visitor *v) { return v->visit(this); }
class SizeVisitor : public Visitor {
public:
size_t visit(File * file) { return file->getSize(); }
size_t visit(Directory *directory) {
size_t size = 0;
Iterator<Entry *> *it = directory->iterator();
while (it->hasNext()) {
Entry *entry = it->next();
size += entry->accept(this);
}
delete it;
return size;
}
};
class ListVisitor : public Visitor {
std::string currentDirectoryName;
std::string saveDirectoryName;
public:
size_t visit(File *file) {
std::cout << currentDirectoryName << "/" << file->getName() << "(" << file->getSize() << ")" << std::endl;
return 0;
}
size_t visit(Directory *dir) {
std::cout << currentDirectoryName << "/" << dir->getName() << "(" << dir->getSize() << ")" << std::endl;
saveDirectoryName = currentDirectoryName;
currentDirectoryName += "/" + dir->getName();
Iterator<Entry *> *it = dir->iterator();
while (it->hasNext()) {
Entry *entry = it->next();
entry->accept(this);
}
delete it;
currentDirectoryName = saveDirectoryName;
return 0;
}
};
size_t Directory::getSize() {
Visitor *visitor = new SizeVisitor();
size_t size = this->accept(visitor);
delete visitor;
return size;
}
void Directory::treePrint() {
Visitor *visitor = new ListVisitor();
this->accept(visitor);
delete visitor;
}
int main() {
{
Directory *rootdir = new Directory("root");
File *file1 = new File("file1.txt", 100);
File *file2 = new File("file2.txt", 200);
rootdir->add(file1);
rootdir->add(file2);
rootdir->treePrint();
delete rootdir;
}
// xmallocdump();
return 0;
}