AnyCollect  1.1.2
Source.cc
Go to the documentation of this file.
1 //
2 // Source.cc
3 //
4 // Created on October 31st 2018
5 //
6 // Copyright 2018 CFM (www.cfm.fr)
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 // http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 //
20 
21 #include <glob.h>
22 
23 #include <boost/filesystem.hpp>
24 
25 #include "Source.h"
26 
27 namespace fs = boost::filesystem;
28 
29 
30 namespace AnyCollect {
31  Source::Source(const std::string& filePath) noexcept :
32  type_(SourceTypeFile),
33  path_(filePath)
34  {
35  fs::path fspath{this->path_};
36  for (const auto& pathPart : fspath.relative_path())
37  this->pathParts_.push_back(pathPart.string());
38  this->reset();
39  }
40 
41  Source::Source(const std::string& program, const std::vector<std::string>& arguments) noexcept :
42  type_(SourceTypeCommand)
43  {
44  this->path_ = program;
45  for (const auto& arg : arguments)
46  this->path_ += " " + arg;
47  this->reset();
48  }
49 
50 
51  std::vector<std::string> Source::filePathsMatchingGlobbingPattern(const std::string& pattern) noexcept {
52  std::vector<std::string> paths;
53  glob_t globbuf;
54 
55  int r = glob(pattern.c_str(), 0, NULL, &globbuf);
56  if (r == 0) {
57  for (size_t i = 0; i < globbuf.gl_pathc; i++) {
58  if (fs::is_regular_file(fs::status(globbuf.gl_pathv[i])))
59  paths.emplace_back(globbuf.gl_pathv[i]);
60  }
61  }
62 
63  globfree(&globbuf);
64  return paths;
65  }
66 
67 
69  return this->type_;
70  }
71 
72  const std::string& Source::path() const noexcept {
73  return this->path_;
74  }
75 
76  const std::vector<std::string>& Source::pathParts() const noexcept {
77  return this->pathParts_;
78  }
79 
80  const std::string_view& Source::contents() const noexcept {
81  return this->contents_;
82  }
83 
84  std::chrono::system_clock::time_point Source::timestamp() const noexcept {
85  return this->timestamp_;
86  }
87 
88  std::vector<std::shared_ptr<Expression>>& Source::expressions() noexcept {
89  return this->expressions_;
90  }
91 
92  const std::vector<std::shared_ptr<Expression>>& Source::expressions() const noexcept {
93  return this->expressions_;
94  }
95 
96 
97  size_t Source::readFile(bool firstTime) {
98  errno = 0;
99  if (firstTime) {
100  this->file_ = std::ifstream(this->path_, std::ios::binary);
101  if (errno) {
102  perror(std::string(this->path_).append(": Error opening file").c_str());
103  errno = 0;
104  return -1;
105  }
106  }
107  this->file_.clear();
108  this->file_.seekg(0);
109  this->file_.read(this->buffer_.data(), this->buffer_.size());
110  if (errno) {
111  perror(std::string(this->path_).append(": Error reading file").c_str());
112  errno = 0;
113  return -1;
114  }
115  return this->file_.gcount();
116  }
117 
118  size_t Source::executeCommand(bool ) {
119  errno = 0;
120  if (this->process_.is_open())
121  this->process_.close();
122  this->process_.clear();
123  this->process_.open(this->path_, redi::pstreambuf::pstdout | redi::pstreambuf::pstderr);
124  this->process_.out().read(this->buffer_.data(), this->buffer_.size());
125  if (this->process_.bad())
126  return -1;
127  else
128  return this->process_.gcount();
129  }
130 
131 
132  bool Source::reset() noexcept {
133  this->buffer_.clear();
134  this->buffer_.resize(1024, '\0');
135 
136  switch (this->type_) {
137  case SourceTypeFile:
138  if (this->readFile(true) == ((size_t)-1))
139  return false;
140  while (!this->file_.eof()) {
141  this->buffer_.resize(this->buffer_.size() * 2, '\0');
142  if (this->readFile(true) == ((size_t)-1))
143  return false;
144  }
145  break;
146  case SourceTypeCommand:
147  if (this->executeCommand(true) == ((size_t)-1))
148  return false;
149  while (!this->process_.eof()) {
150  this->buffer_.resize(this->buffer_.size() * 2, '\0');
151  if (this->executeCommand(true) == ((size_t)-1))
152  return false;
153  }
154  break;
155  }
156 
157  this->buffer_.resize(this->buffer_.size() * 2, '\0');
158  return true;
159  }
160 
161  bool Source::update() noexcept {
162  size_t size = 0;
163  switch (this->type_) {
164  case SourceTypeFile:
165  size = this->readFile(false);
166  break;
167  case SourceTypeCommand:
168  size = this->executeCommand(false);
169  break;
170  }
171  if (size == ((size_t)-1)) {
172  if (!this->reset())
173  return false;
174  }
175 
176  this->buffer_[size] = '\0';
177  this->contents_ = std::string_view{this->buffer_.data(), size};
178  this->timestamp_ = std::chrono::system_clock::now();
179  return true;
180  }
181 
182  std::string_view::const_iterator Source::begin() const noexcept {
183  return this->contents_.cbegin();
184  }
185 
186  std::string_view::const_iterator Source::end() const noexcept {
187  return this->contents_.cend();
188  }
189 
190  std::string_view::const_iterator Source::getLine(std::string_view::const_iterator begin) const noexcept {
191  auto end = begin;
192  while (end != this->end() && *end != '\n')
193  end++;
194  return end;
195  }
196 }
std::string_view contents_
Read-only view on the buffer_.
Definition: Source.h:57
std::ifstream file_
For file sources, the file descriptor.
Definition: Source.h:53
const std::string & path() const noexcept
Returns the file path or command to execute.
Definition: Source.cc:72
bool reset() noexcept
Resets the source: attempts to open the file or execute the command, allocates enough space for conte...
Definition: Source.cc:132
SourceType
Enum of existing source type.
Definition: Source.h:44
std::string_view::const_iterator getLine(std::string_view::const_iterator begin) const noexcept
Returns an iterator to the end of the specified line.
Definition: Source.cc:190
std::vector< char > buffer_
Buffer for file contents or command output.
Definition: Source.h:55
std::string_view::const_iterator begin() const noexcept
Returns the iterator to the beginning of the source&#39;s contents.
Definition: Source.cc:182
std::chrono::system_clock::time_point timestamp() const noexcept
Returns the timestamp of stored contents.
Definition: Source.cc:84
bool update() noexcept
Updates the source (read the file or execute command) and store the results.
Definition: Source.cc:161
redi::ipstream process_
For command sources, the child process.
Definition: Source.h:54
Command output source.
Definition: Source.h:46
std::vector< std::shared_ptr< Expression > > expressions_
Array of expressions used on the source&#39;s contents.
Definition: Source.h:60
std::string_view::const_iterator end() const noexcept
Returns the iterator to the end of the source&#39;s contents.
Definition: Source.cc:186
static std::vector< std::string > filePathsMatchingGlobbingPattern(const std::string &pattern) noexcept
Returns all file paths that match a pattern as defined by POSIX.
Definition: Source.cc:51
const std::vector< std::string > & pathParts() const noexcept
For file sources, returns the different parts of the file&#39;s path.
Definition: Source.cc:76
const std::string_view & contents() const noexcept
Returns the stored contents (file contents or command output)
Definition: Source.cc:80
SourceType type_
The type of the source.
Definition: Source.h:50
File contents source.
Definition: Source.h:45
std::chrono::system_clock::time_point timestamp_
Last contents or output fetching time.
Definition: Source.h:58
std::vector< std::string > pathParts_
For file sources, the parts of the file&#39;s path.
Definition: Source.h:52
Source(const std::string &filePath) noexcept
Construct a new Source object of file type.
Definition: Source.cc:31
std::string path_
Path of the file or command to execute.
Definition: Source.h:51
size_t readFile(bool firstTime=false)
For file sources, put the file contents into the buffer_.
Definition: Source.cc:97
SourceType type()
Returns the source type.
Definition: Source.cc:68
std::vector< std::shared_ptr< Expression > > & expressions() noexcept
Returns the array of the receiver&#39;s expressions.
Definition: Source.cc:88
size_t executeCommand(bool firstTime=false)
For command sources, put the command output into the buffer_.
Definition: Source.cc:118