CodeCompass
112 строк · 2.1 Кб
1#include <chrono>
2
3#include <boost/filesystem.hpp>
4
5#include <util/logutil.h>
6#include <util/parserutil.h>
7
8namespace fs = boost::filesystem;
9
10namespace
11{
12
13/**
14* Context to iterateDirectoryRecursive.
15*/
16struct TraverseContext
17{
18/**
19* Time of last status report.
20*/
21std::chrono::time_point<std::chrono::system_clock> lastReportTime =
22std::chrono::system_clock::now();
23/**
24* Total number of (regular) files visited in the iteration.
25*/
26std::size_t numFilesVisited = 0;
27/**
28* Total number of directories visited in the iteration.
29*/
30std::size_t numDirsVisited = 0;
31};
32
33bool iterateDirectoryRecursive(
34TraverseContext& context_,
35const std::string& path_,
36cc::util::DirIterCallback callback_)
37{
38//--- Status reporting ---//
39
40auto currTime = std::chrono::system_clock::now();
41if ((currTime - context_.lastReportTime) >= std::chrono::seconds(15))
42{
43// It's time to report
44LOG(info)
45<< "Recursive directory iteration: visited "
46<< context_.numFilesVisited << " files in "
47<< context_.numDirsVisited << " directories so far.";
48context_.lastReportTime = currTime;
49}
50
51fs::path p(path_);
52
53boost::system::error_code ec;
54auto target = fs::canonical(p, ec);
55if (ec)
56{
57LOG(warning) << p << ": " << ec.message();
58return true;
59}
60
61if (!fs::exists(p))
62{
63LOG(warning) << "Not found: " << p;
64return true;
65}
66
67if (fs::is_directory(p))
68{
69++context_.numDirsVisited;
70}
71else if(fs::is_regular_file(p))
72{
73++context_.numFilesVisited;
74}
75
76//--- Call callback ---//
77
78if (!callback_(path_))
79return false;
80
81//--- Iterate over directory content ---//
82
83if (fs::is_directory(p))
84for (fs::directory_iterator it(p), end_iter; it != end_iter; ++it)
85{
86std::string path = it->path().c_str();
87
88if (!iterateDirectoryRecursive(context_, path , callback_))
89continue;
90}
91
92return true;
93}
94
95} // anonymus namespace
96
97namespace cc
98{
99namespace util
100{
101
102bool iterateDirectoryRecursive(
103const std::string& path_,
104DirIterCallback callback_)
105{
106TraverseContext ctx;
107std::string path = path_;
108return ::iterateDirectoryRecursive(ctx, path, callback_);
109}
110
111}
112}
113