se2ez
io.cpp
Go to the documentation of this file.
1 /* Author: Zachary Kingston */
2 
3 #include <cstdlib>
4 #include <memory>
5 #include <array>
6 #include <stdexcept>
7 #include <chrono>
8 #include <thread>
9 
10 #include <boost/format.hpp>
11 #include <boost/filesystem.hpp>
12 
13 #include <se2ez/core/io.h>
14 
15 using namespace se2ez;
16 
17 namespace
18 {
19  boost::filesystem::path expandHome(const boost::filesystem::path &in)
20  {
21  const char *home = std::getenv("HOME");
22  if (home == nullptr)
23  {
24  throw std::runtime_error("HOME Environment variable is not set! Cannot resolve ~ in path.");
25  return in;
26  }
27 
28  boost::filesystem::path out;
29  for (const auto &p : in)
30  out /= (p.string() == "~") ? home : p;
31 
32  return out;
33  }
34 
35  boost::filesystem::path expandSymlinks(const boost::filesystem::path &in)
36  {
37  boost::filesystem::path out;
38  for (const auto &p : in)
39  {
40  auto tmp = out / p;
41  if (boost::filesystem::is_symlink(tmp))
42  out = boost::filesystem::read_symlink(tmp);
43  else
44  out /= p;
45  }
46 
47  return out;
48  }
49 
50  boost::filesystem::path expandPath(const boost::filesystem::path &in)
51  {
52  boost::filesystem::path out = in;
53  out = expandHome(out);
54  out = expandSymlinks(out);
55 
56  return boost::filesystem::absolute(out);
57  }
58 
59  // is lhs a prefix of rhs?
60  // bool isPrefix(const std::string &lhs, const std::string &rhs)
61  // {
62  // return std::equal(lhs.begin(), lhs.begin() + std::min(lhs.size(), rhs.size()), rhs.begin());
63  // }
64 
65  // is lhs a suffix? of rhs?
66  bool isSuffix(const std::string &lhs, const std::string &rhs)
67  {
68  return std::equal(lhs.rbegin(), lhs.rbegin() + std::min(lhs.size(), rhs.size()), rhs.rbegin());
69  }
70 
71  bool isExtension(const std::string &path_string, const std::string &extension)
72  {
73  boost::filesystem::path path(path_string);
74  const std::string last = boost::filesystem::extension(path);
75  return isSuffix(extension, last);
76  }
77 } // namespace
78 
80 {
81  boost::filesystem::path file = expandPath(path).string();
82 
83  if (!boost::filesystem::exists(file))
84  throw std::invalid_argument((boost::format("File `%1%` does not exist.") % path).str());
85 
86  return boost::filesystem::canonical(boost::filesystem::absolute(file)).string();
87 }
88 
90 {
91  const std::string full_path = resolvePath(path);
92  if (full_path.empty())
93  return "";
94 
95  std::ifstream ifs(full_path.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
96 
97  std::ifstream::pos_type size = ifs.tellg();
98  ifs.seekg(0, std::ios::beg);
99 
100  std::vector<char> bytes(size);
101  ifs.read(bytes.data(), size);
102 
103  return std::string(bytes.data(), size);
104 }
105 
107 {
108  std::array<char, 128> buffer;
109  std::string result;
110  std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
111  if (!pipe)
112  throw std::runtime_error((boost::format("Failed to run command `%1%`!") % cmd).str());
113 
114  while (!feof(pipe.get()))
115  {
116  if (fgets(buffer.data(), 128, pipe.get()) != nullptr)
117  result += buffer.data();
118  }
119 
120  return result;
121 }
122 
124 {
125  YAML::Node file;
126  const std::string full_path = resolvePath(path);
127  if (full_path.empty())
128  return std::make_pair(false, file);
129 
130  if (!isExtension(full_path, "yml") && !isExtension(full_path, "yaml"))
131  return std::make_pair(false, file);
132 
133  try
134  {
135  return std::make_pair(true, YAML::LoadFile(full_path));
136  }
137  catch (std::exception &e)
138  {
139  return std::make_pair(false, file);
140  }
141 }
142 
143 bool io::YAMLToFile(const YAML::Node &node, const std::string &file)
144 {
145  YAML::Emitter out;
146  out << node;
147 
148  std::ofstream fout;
149  io::createFile(fout, file);
150 
151  fout << out.c_str();
152  fout.close();
153 
154  return true;
155 }
156 
158 {
159  boost::filesystem::create_directories(dir);
160 }
161 
162 void io::createFile(std::ofstream &out, const std::string &file)
163 {
164  boost::filesystem::path path(file);
165  path = expandHome(path);
166  path = expandSymlinks(path);
167 
168  const auto parent = path.parent_path().string();
169 
170  if (!parent.empty())
171  io::createDirectory(parent);
172 
173  out.open(path.string(), std::ofstream::out | std::ofstream::trunc);
174 }
175 
177 {
178  std::vector<std::string> contents;
179 
180  const std::string full_path = resolvePath(directory);
181  if (full_path.empty())
182  return std::make_pair(false, contents);
183 
184  boost::filesystem::path path(full_path);
185  if (!boost::filesystem::is_directory(path))
186  return std::make_pair(false, contents);
187 
188  for (auto it = boost::filesystem::directory_iterator(path); it != boost::filesystem::directory_iterator();
189  ++it)
190  contents.emplace_back(expandPath(it->path()).string());
191 
192  return std::make_pair(true, contents);
193 }
194 
195 boost::posix_time::ptime io::getDate()
196 {
197  return boost::posix_time::microsec_clock::local_time();
198 }
199 
201 {
202  boost::char_separator<char> seps(separators.c_str());
203  boost::tokenizer<boost::char_separator<char>> tokenizer(s, seps);
204  return std::vector<std::string>(tokenizer.begin(), tokenizer.end());
205 }
206 
207 void io::sleep(double seconds)
208 {
209  std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<long int>(seconds * 1000)));
210 }
T empty(T... args)
T open(T... args)
void sleep(double seconds)
Have this thread sleep for some number of seconds.
Definition: io.cpp:207
const std::string loadFileToString(const std::string &path)
Loads a file to a string.
Definition: io.cpp:89
void createDirectory(const std::string &dir)
Creates a directory.
Definition: io.cpp:157
T sleep_for(T... args)
const std::pair< bool, YAML::Node > loadFileToYAML(const std::string &path)
Loads a file to a YAML node.
Definition: io.cpp:123
T getenv(T... args)
T min(T... args)
T data(T... args)
void createFile(std::ofstream &out, const std::string &file)
Creates a file and opens an output stream. Creates directories if they do not exist.
Definition: io.cpp:162
T close(T... args)
T make_pair(T... args)
boost::posix_time::ptime getDate()
Get the current time (up to milliseconds)
Definition: io.cpp:195
T tellg(T... args)
T get(T... args)
std::vector< std::string > tokenize(const std::string &string, const std::string &separators)
Separates a string into tokens, based upon separators.
Definition: io.cpp:200
T size(T... args)
T c_str(T... args)
std::string format(const std::string &fmt, Args &&... args)
Definition: log.h:25
Main namespace.
Definition: collision.h:11
const std::string runCommand(const std::string &cmd)
Runs a command cmd and returns stdout as a string.
Definition: io.cpp:106
bool YAMLToFile(const YAML::Node &node, const std::string &file)
Write the contents of a YAML node out to a potentially new file.
Definition: io.cpp:143
const std::string resolvePath(const std::string &path)
Resolves file paths to their canonical form.
Definition: io.cpp:79
const std::pair< bool, std::vector< std::string > > listDirectory(const std::string &directory)
Lists of the contents of a directory.
Definition: io.cpp:176
T equal(T... args)
T emplace_back(T... args)
T rbegin(T... args)