2
0

FilesTree.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include "FilesTree.h"
  2. #include "PackFile.h"
  3. FilesTree::Node::Node() : path(_FL_),
  4. children(_FL_)
  5. {
  6. parent = null;
  7. }
  8. FilesTree::FilesTree() : paths(_FL_)
  9. {
  10. root.parent = null;
  11. pathsCount = 0;
  12. }
  13. FilesTree::~FilesTree()
  14. {
  15. }
  16. //Добавить объект отображающий путь
  17. void FilesTree::AddMirrorPath(MirrorPath * mp, const char * on)
  18. {
  19. //Получаем последний нод в пути
  20. Node * node = AddPath(root, on);
  21. Assert(node);
  22. //Регистрируемся в ноде
  23. node->path.Add(mp);
  24. mp->SetNode(node);
  25. }
  26. //Добавить новый путь и вернуть конечный узел
  27. FilesTree::Node * FilesTree::AddPath(Node & node, const char * path)
  28. {
  29. //Выделяем текущее имя
  30. for(long size = 0; path[size] != '\\' && path[size]; size++);
  31. //Если нет продолжения то возвращаем родительский нод
  32. if(size == 0)
  33. {
  34. return &node;
  35. }
  36. //Ищем среди детей
  37. for(long i = 0; i < node.children; i++)
  38. {
  39. Node & child = *node.children[i];
  40. if(IsEqual(child.name.c_str(), child.name.Len(), path, size))
  41. {
  42. if(path[size])
  43. {
  44. return AddPath(child, path + size + 1);
  45. }
  46. return &child;
  47. }
  48. }
  49. //Нет такого, добавляем
  50. Node * n = NEW Node();
  51. n->name.Reserve(size + 1);
  52. for(long i = 0; i < size; i++)
  53. {
  54. n->name += path[i];
  55. }
  56. node.children.Add(n);
  57. n->parent = &node;
  58. return AddPath(*n, path + size + 1);
  59. }
  60. //Удалить объект отображающий путь
  61. void FilesTree::DelMirrorPath(MirrorPath * mp)
  62. {
  63. Node * node = (Node *)mp->GetNode();
  64. Assert(node);
  65. node->path.Del(mp);
  66. //Удаляем цепочку пустых нодов
  67. while(node->children.Size() == 0 && node->path.Size() == 0 && node->parent)
  68. {
  69. Node * parent = node->parent;
  70. parent->children.Del(node);
  71. delete node;
  72. node = parent;
  73. }
  74. }
  75. //Получить список зеркальных путей
  76. dword FilesTree::FindPaths(const char * fullPath)
  77. {
  78. pathsCount = 0;
  79. //Ищем по зеркальным путям в паках
  80. TreeProcess(root, fullPath);
  81. return pathsCount;
  82. }
  83. //Получить путь из списка
  84. const char * FilesTree::GetPath(dword index)
  85. {
  86. if(index < pathsCount)
  87. {
  88. return paths[index].c_str();
  89. }
  90. return null;
  91. }
  92. //Поиск всех путей и проверка файлов в паке
  93. void FilesTree::TreeProcess(Node & node, const char * fullPath)
  94. {
  95. //Перебираем все отзеркаленые пути
  96. for(long i = 0; i < node.path; i++)
  97. {
  98. MirrorPath * p = node.path[i];
  99. if(pathsCount >= paths.Size())
  100. {
  101. paths.AddElements(16);
  102. for(dword i = pathsCount; i < paths.Size(); i++)
  103. {
  104. paths[i].Reserve(1024);
  105. }
  106. }
  107. string & path = paths[pathsCount++];
  108. path = node.path[i]->GetPath();
  109. path += fullPath;
  110. }
  111. if(*fullPath == 0)
  112. {
  113. //Закончились поиски
  114. return;
  115. }
  116. //Выделяем текущее имя
  117. for(long size = 0; fullPath[size] != '\\' && fullPath[size]; size++);
  118. //Ищем среди детей
  119. for(long i = 0; i < node.children; i++)
  120. {
  121. Node & child = *node.children[i];
  122. if(IsEqual(child.name.c_str(), child.name.Len(), fullPath, size))
  123. {
  124. const char * path = fullPath + size;
  125. if(*path == '\\') path++;
  126. TreeProcess(child, path);
  127. return;
  128. }
  129. }
  130. }
  131. //Сравнить строки
  132. bool FilesTree::IsEqual(const char * str1, long len1, const char * str2, long len2)
  133. {
  134. if(len1 != len2)
  135. {
  136. return false;
  137. }
  138. for(; len1 > 0; len1--, str1++, str2++)
  139. {
  140. if(*str1 != *str2)
  141. {
  142. return false;
  143. }
  144. }
  145. return true;
  146. }