fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4.  
  5. class Visitor;
  6.  
  7. class Entry {
  8. public:
  9. virtual ~Entry() {};
  10. virtual std::string getName() const = 0;
  11. virtual size_t getSize() = 0;
  12. virtual size_t accept(Visitor *v) = 0;
  13. };
  14.  
  15. template <class T>
  16. class Iterator {
  17. public:
  18. virtual ~Iterator() {}
  19. virtual bool hasNext() = 0;
  20. virtual T next() = 0;
  21. };
  22.  
  23. template <class T>
  24. class VectorIterator : public Iterator<T> {
  25. std::vector<T> &v;
  26. size_t index = 0;
  27. public:
  28. VectorIterator(std::vector<T> &v) : v(v) {}
  29. bool hasNext() override {
  30. if (index < v.size())
  31. return true;
  32. else
  33. return false;
  34. }
  35. T next() {
  36. T retvalue = v[index];
  37. index++;
  38. return retvalue;
  39. }
  40. };
  41.  
  42. class File : public Entry {
  43. std::string name;
  44. size_t size;
  45. public:
  46. File(std::string name, size_t size) : name(name), size(size) {}
  47. std::string getName() const override { return name; }
  48. size_t getSize() override { return size; }
  49. size_t accept(Visitor *v) override;
  50. };
  51.  
  52. class Directory : public Entry {
  53. std::string name;
  54. std::vector<Entry *> v;
  55. public:
  56. Directory(std::string name) : name(name) {}
  57. ~Directory() {
  58. for (auto p : v) delete p;
  59. }
  60. std::string getName() const override { return name; }
  61. size_t getSize() override;
  62. size_t accept(Visitor *v) override;
  63. void treePrint();
  64. void add(Entry *entry) { v.push_back(entry); }
  65. Iterator<Entry *> *iterator() { return new VectorIterator<Entry *>(v); }
  66. };
  67.  
  68. class Visitor {
  69. public:
  70. virtual ~Visitor() {}
  71. virtual size_t visit(File *) = 0;
  72. virtual size_t visit(Directory *) = 0;
  73. };
  74.  
  75. size_t File::accept(Visitor *v) { return v->visit(this); }
  76. size_t Directory::accept(Visitor *v) { return v->visit(this); }
  77.  
  78. class SizeVisitor : public Visitor {
  79. public:
  80. size_t visit(File * file) { return file->getSize(); }
  81. size_t visit(Directory *directory) {
  82. size_t size = 0;
  83. Iterator<Entry *> *it = directory->iterator();
  84. while (it->hasNext()) {
  85. Entry *entry = it->next();
  86. size += entry->accept(this);
  87. }
  88. delete it;
  89. return size;
  90. }
  91. };
  92.  
  93. class ListVisitor : public Visitor {
  94. std::string currentDirectoryName;
  95. std::string saveDirectoryName;
  96.  
  97. public:
  98. size_t visit(File *file) {
  99. std::cout << currentDirectoryName << "/" << file->getName() << "(" << file->getSize() << ")" << std::endl;
  100. return 0;
  101. }
  102. size_t visit(Directory *dir) {
  103. std::cout << currentDirectoryName << "/" << dir->getName() << "(" << dir->getSize() << ")" << std::endl;
  104. saveDirectoryName = currentDirectoryName;
  105. currentDirectoryName += "/" + dir->getName();
  106. Iterator<Entry *> *it = dir->iterator();
  107. while (it->hasNext()) {
  108. Entry *entry = it->next();
  109. entry->accept(this);
  110. }
  111. delete it;
  112. currentDirectoryName = saveDirectoryName;
  113. return 0;
  114. }
  115. };
  116.  
  117. size_t Directory::getSize() {
  118. Visitor *visitor = new SizeVisitor();
  119. size_t size = this->accept(visitor);
  120. delete visitor;
  121. return size;
  122. }
  123. void Directory::treePrint() {
  124. Visitor *visitor = new ListVisitor();
  125. this->accept(visitor);
  126. delete visitor;
  127. }
  128.  
  129. int main() {
  130. {
  131. Directory *rootdir = new Directory("root");
  132. File *file1 = new File("file1.txt", 100);
  133. File *file2 = new File("file2.txt", 200);
  134. rootdir->add(file1);
  135. rootdir->add(file2);
  136. rootdir->treePrint();
  137.  
  138. delete rootdir;
  139. }
  140. // xmallocdump();
  141. return 0;
  142. }
  143.  
  144.  
Success #stdin #stdout 0.01s 5272KB
stdin
Standard input is empty
stdout
/root(300)
/root/file1.txt(100)
/root/file2.txt(200)