Crombie Tools
Misc.h
Go to the documentation of this file.
1 #ifndef CROMBIE_MISC_H
2 #define CROMBIE_MISC_H
3 
4 #include <iostream>
5 #include <string>
6 #include <sstream>
7 #include <iterator>
8 #include <cstdlib>
9 #include <memory>
10 #include <stdexcept>
11 #include <array>
12 #include <vector>
13 
14 #include "crombie/Debug.h"
15 #include "crombie/Types.h"
16 
17 #include "TROOT.h"
18 
19 namespace crombie {
20  namespace Misc {
21 
22  void draw_progress(unsigned progress, unsigned max) {
23 
24  Debug::Debug(__PRETTY_FUNCTION__, "progress", progress, max);
25 
26  if (max) {
27  // Draw shitty progress bar
28  std::cout << '\r' << '[';
29  for (unsigned i = 0; i < max; i++) {
30  if (i < progress)
31  std::cout << '=';
32  else if (i == progress)
33  std::cout << '>';
34  else
35  std::cout << ' ';
36  }
37  std::cout << "] " << progress * 100/max << '%';
38  std::flush(std::cout);
39  }
40  else
41  throw std::runtime_error{"Nothing to run over."};
42  }
43 
44  /**
45  Split the contents of a string into multiple strings.
46  This is different than crombie::Misc::split because it can split over multiple spaces,
47  while spilt_string only splits over one character at a time.
48  */
49  Types::strings tokenize(const std::string& str) {
50  std::istringstream ss {str};
51  Types::strings output {
52  std::istream_iterator<std::string>{ss},
53  std::istream_iterator<std::string>{}
54  };
55  return output;
56  }
57 
58  /// Splits a string.
59  Types::strings split(const std::string& str, const std::string& delim = "\n") {
60  Types::strings output;
61  std::string::size_type prev = 0;
62  for(auto pos = str.find(delim);
63  pos != std::string::npos;
64  prev = pos + delim.size(), pos = str.find(delim, prev))
65  output.push_back(str.substr(prev, pos - prev));
66 
67  auto last = str.substr(prev);
68  if (last.size())
69  output.push_back(last);
70 
71  Debug::Debug(__PRETTY_FUNCTION__, output.size());
72 
73  return output;
74  }
75 
76  /// Get the output of a shell command
77  std::string shell(const std::string& cmd) {
78  std::array<char, 128> buffer;
79  std::string output;
80  std::shared_ptr<FILE> pipe(popen(cmd.data(), "r"), pclose);
81  if (not pipe)
82  throw std::runtime_error("popen() failed");
83  while(not feof(pipe.get())) {
84  if (fgets(buffer.data(), 128, pipe.get()))
85  output += buffer.data();
86  }
87  Debug::Debug(__PRETTY_FUNCTION__, cmd, "---", output);
88  return output;
89  }
90 
91  /// Get an environment variable by name, with an optional fallback value
92  std::string env(const std::string& variable, const std::string& fallback = "") {
93  if (variable == "nthreads")
94  ROOT::EnableThreadSafety();
95 
96  auto* output = getenv(variable.data());
97  if (output)
98  return std::string(output);
99  if (not fallback.size())
100  throw std::runtime_error(std::string("Requesting non-existent variable '") + variable + "' with no fallback");
101  return std::string(fallback);
102  }
103 
104  template<typename O, typename C, typename F>
105  std::vector<O> comprehension (const C& container, const F& func) {
106  std::vector<O> output {};
107  for (auto& iter : container)
108  output.push_back(func(iter));
109  return output;
110  }
111 
112  }
113 }
114 
115 #endif