/win32/shellext/Directory.cpp

https://bitbucket.org/tortoisehg/hgtk/ · C++ · 240 lines · 181 code · 44 blank · 15 comment · 45 complexity · c04dff22443d36d0de4b4fdc7863397c MD5 · raw file

  1. // Copyright (C) 2009 Benjamin Pollack
  2. // Copyright (C) 2009 Adrian Buehlmann
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 2 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #include <time.h>
  17. #include "stdafx.h"
  18. #include "Directory.h"
  19. #include "Winstat.h"
  20. Directory::Directory(
  21. Directory* p, const std::string& n, const std::string& basepath
  22. ):
  23. parent_(p), name_(n)
  24. {
  25. if (n.empty())
  26. path_ = basepath;
  27. else if (basepath.empty())
  28. path_ = n;
  29. else
  30. path_ = basepath + '/' + n;
  31. }
  32. Directory::~Directory()
  33. {
  34. for (DirsT::iterator i = subdirs_.begin(); i != subdirs_.end(); ++i)
  35. {
  36. delete *i;
  37. }
  38. }
  39. int splitbase(const std::string& n, std::string& base, std::string& rest)
  40. {
  41. if (n.empty())
  42. return 0;
  43. size_t x = n.find_first_of ('/');
  44. if (x == std::string::npos)
  45. {
  46. base.clear();
  47. rest = n;
  48. return 1;
  49. }
  50. if (x == 0 || x == n.length()-1)
  51. return 0;
  52. base = n.substr(0, x);
  53. rest = n.substr(x+1);
  54. return 1;
  55. }
  56. int Directory::add(const std::string& n_in, Direntry& e)
  57. {
  58. std::string base;
  59. std::string rest;
  60. std::string n = n_in;
  61. Directory* cur = this;
  62. for (;;)
  63. {
  64. if (!splitbase(n, base, rest)) {
  65. TDEBUG_TRACE("Directory(" << path() << ")::add(" << n_in
  66. << "): splitbase returned 0");
  67. return 0;
  68. }
  69. if (base.empty())
  70. {
  71. e.name = n;
  72. cur->files_.push_back(e);
  73. return 1;
  74. }
  75. Directory* d = 0;
  76. for (DirsT::iterator i = cur->subdirs_.begin();
  77. i != cur->subdirs_.end(); ++i)
  78. {
  79. if ((*i)->name_ == base) {
  80. d = *i;
  81. break;
  82. }
  83. }
  84. if (!d)
  85. {
  86. d = new Directory(cur, base, cur->path());
  87. cur->subdirs_.push_back(d);
  88. }
  89. n = rest;
  90. cur = d;
  91. }
  92. }
  93. const Direntry* Directory::get(const std::string& n_in) const
  94. {
  95. std::string base;
  96. std::string rest;
  97. std::string n = n_in;
  98. const Directory* cur = this;
  99. for (;;)
  100. {
  101. loopstart:
  102. if (!splitbase(n, base, rest))
  103. {
  104. TDEBUG_TRACE("Directory(" << path() << ")::get("
  105. << n_in << "): splitbase returned 0");
  106. return 0;
  107. }
  108. if (base.empty())
  109. {
  110. for (FilesT::const_iterator i = cur->files_.begin();
  111. i != cur->files_.end(); ++i)
  112. {
  113. if (i->name == n)
  114. return &(*i);
  115. }
  116. return 0;
  117. }
  118. for (DirsT::const_iterator i = cur->subdirs_.begin();
  119. i != cur->subdirs_.end(); ++i)
  120. {
  121. if ((*i)->name_ == base)
  122. {
  123. cur = *i;
  124. n = rest;
  125. goto loopstart;
  126. }
  127. }
  128. return 0;
  129. }
  130. }
  131. Directory* Directory::getdir(const std::string& n_in)
  132. {
  133. std::string base;
  134. std::string rest;
  135. std::string n = n_in;
  136. const Directory* cur = this;
  137. for (;;)
  138. {
  139. loopstart:
  140. if (!splitbase(n, base, rest))
  141. {
  142. TDEBUG_TRACE("Directory(" << path() << ")::getdir("
  143. << n_in << "): splitbase returned 0");
  144. return 0;
  145. }
  146. const bool leaf = base.empty();
  147. const std::string& searchstr = (leaf ? n : base);
  148. for (DirsT::const_iterator i = cur->subdirs_.begin();
  149. i != cur->subdirs_.end(); ++i)
  150. {
  151. if ((*i)->name_ == searchstr)
  152. {
  153. if (leaf)
  154. return *i;
  155. cur = *i;
  156. n = rest;
  157. goto loopstart;
  158. }
  159. }
  160. return 0;
  161. }
  162. }
  163. void Directory::print() const
  164. {
  165. for (DirsT::const_iterator i = subdirs_.begin(); i != subdirs_.end(); ++i)
  166. {
  167. const Directory* d = *i;
  168. if (!d)
  169. {
  170. TDEBUG_TRACE("Directory(" << path() << ")::print: error: d is 0");
  171. return;
  172. }
  173. d->print();
  174. }
  175. std::string base = path();
  176. time_t t;
  177. std::string s;
  178. char* ctime_res = 0;
  179. for (FilesT::const_iterator i = files_.begin(); i != files_.end(); ++i)
  180. {
  181. std::string p = (!base.empty() ? base + "/" + i->name : i->name);
  182. t = i->mtime;
  183. ctime_res = ctime(&t);
  184. if (ctime_res) {
  185. s = ctime_res;
  186. s.resize(s.size() - 1); // strip ending '\n'
  187. }
  188. else {
  189. s = "unset";
  190. }
  191. printf(
  192. "%c %6o %10u %-24s %s\n",
  193. i->state, i->mode, i->size, s.c_str(), p.c_str()
  194. );
  195. }
  196. }